ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React Native 002
    React/React Native 2022. 12. 30. 02:01
    728x90

    미국에 돌아온 지 3일째다 시차적응 때문에 힘들고.. 어제까지는 수업 수료하는 날이라 바쁘고 와이프 비자 발급 받으라 정신이 없었는데 오늘은 내 신분 챙기는 서류 보내느라 바빴다.  그래도 인터뷰때 한 마디라도 더 해보려면 어느정도 앱을 만들어 봐야 할 것 같아서 남은 시간 더 해보자..

     

    Core Components

    주로 사용되는 컴포넌트들은 이런게 있다

    Todo App만들기

    목표 : 리액트 네이티브의 core components를 최대한 많이 사용하면서 개발하기

    코어 컴포넌트 확인 https://reactnative.dev/docs/components-and-apis

    구조

    rnfes - 코어 컴포넌트 사용

    App.js에 있는 ui를 MainScreen으로 가져온다

    import { SafeAreaView, StyleSheet, Text, View } from 'react-native'
    import React from 'react'
    
    const MainScreen = () => {
      return (
        <SafeAreaView>
          <Text>ToDo App</Text>
        </SafeAreaView>
      )
    }
    
    export default MainScreen
    
    const styles = StyleSheet.create({})

     

    <SafeAreaView>

    이것의 목적은 장치의 안전 영역 경계 내에서 콘텐츠를 렌더링하는 것
    (현재 iOS 버전 11 이상이 설치된 iOS기기 에만 적용된다.)

    SafeAreaView를 적용하지 않으면 이렇게 된다.

    <StatusBar> 컴포넌트

    앱의 상태 표시줄을 제어하는 구성요소이다. 상태 표시줄은 일반적으로 화면 상단에 있는 영역으로 현재시간, WiFi 및 배터리 정보 아이콘을 표시한다. https://reactnative.dev/docs/statusbar

     

    StatusBar · React Native

    Component to control the app's status bar. The status bar is the zone, typically at the top of the screen, that displays the current time, Wi-Fi and cellular network information, battery level and/or other status icons.

    reactnative.dev

    적용하면서 바꿔볼 수 있다.

    간단하게 만들어보자

    import { SafeAreaView, StyleSheet, Text, View, StatusBar } from 'react-native'
    import React from 'react'
    
    const MainScreen = () => {
      return (
        <SafeAreaView>
            <StatusBar barStyle={'default'} />
            <Text>ToDo App</Text>
            <View>
                <Text>할 일</Text>
            </View>
            <View>
                <Text>완료된 일</Text>
            </View>        
        </SafeAreaView>
      )
    }
    
    export default MainScreen
    
    const styles = StyleSheet.create({})

    잘 출력된다.

    StyleSheet 사용하기

    https://reactnative.dev/docs/style

     

    Style · React Native

    With React Native, you style your application using JavaScript. All of the core components accept a prop named style. The style names and values usually match how CSS works on the web, except names are written using camel casing, e.g. backgroundColor rathe

    reactnative.dev

    web은 css를 사용해서 스타일링을 하는데 React Native에서는 css가 아닌 JS를 사용해서 스타일링을 한다.
    코어 컴포넌트에 styles prop을 가지고 있다. 카멜케이스를 사용하면 된다.
    인라인 스타일로 넣어줄 수도 있고 StyleSheet를 사용해 넣어줄 수도 있다. 역시 이 방법이 가독성이 좋기 때문에 더 추천된다. 이미 정해놓은 스타일을 캐시해주기 때문에 성능도 좋아지게 된다.

     

    예시

    import { Platform, SafeAreaView, StyleSheet, Text, View} from 'react-native'
    import React from 'react'
    import { StatusBar } from 'expo-status-bar'
    
    const MainScreen = () => {
      return (
        <SafeAreaView style={styles.container}>
            <StatusBar barStyle={'default'}></StatusBar>
            <Text style={styles.pageTitle}>ToDo App</Text>
            <View style={styles.listView}>
                <Text style={styles.listTitle}>할 일</Text>
            </View>
            <View style={styles.separator} />
            <View style={styles.listView}>
                <Text style={styles.listTitle}>완료된 일</Text>
            </View>        
        </SafeAreaView>
      )
    }
    
    export default MainScreen
    
    const styles = StyleSheet.create({
        container:{
            flex:1,
            paddingTop: Platform.OS==='android'? 20 : 0, //안드로이드일때는 20을 아니면 0
            backgroundColor: '#F7f8fa',
        },
        pageTitle:{
            marginBottom:35,
            paddingHorizontal:15,
            fontSize:54,
            fontWeight:'600',
        },
        separator:{
            marginHorizontal:10,
            marginTop:25,
            marginBottom:10,
            borderBottomWidth:1,
            borderBottomColor:'#rgba(0,0,0,0.2)',
        },
        listView:{
            flex:1,
        },
        listTitle:{
            marginBottom:25,
            paddingHorizontal:15,
            fontSize:41,
            fontWeight:'500',
        }
    })

    스타일을 입히는거는 사실 별반 다를게 없어 보인다. 근데 스타일시트를 따로 컴포넌트로 떼어서는 적용할 수 없는건가?

    FlexBox

    flex는 항목이 주 축을 따라 사용 가능한 공간을 채울 방법을 정의한다 각 요소의 속성 공간에 따라 분할된다.
    web과 사용방법이 다르지 않다.

    InputForm

    <KeyboardAvoidingView>

    가상 키보드에서 벗어나야 하는 뷰의 일반적이 뭄ㄴ제를 ㅐ결하기 위한 구성요소. 키보드 높이에 따라 높이, 위치, 또는 아래쪽 패딩을 자동으로 조정한다.

     

    behavior prop에 속성값을 줄 수 있다.

    • padding 키보드가 열렸을 때 뷰의 하단에 패딩 설정
    • height 뷰의 높이 자체 변경
    • position 뷰의 위치 설정
    import { KeyboardAvoidingView, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'
    import React from 'react'
    
    const InputForm = () => {
      return (
        <KeyboardAvoidingView
            behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
            style={styles.addFormContainer}>
                <TextInput
                    style={styles.inputField}
                    placeholder="할 일을 작성해 주세요" 
                />
                <Pressable style={styles.addButton}>
                    <Text style={styles.addButtonText}>+</Text>
                </Pressable>
        </KeyboardAvoidingView>
      )
    }
    
    export default InputForm
    
    const styles = StyleSheet.create({
        addFormContainer:{
            flexDirection:'row',
            marginTop:'auto',
            marginBottom:30,
            paddingHorizontal:20,
            backgroundColor:'f7f8fa',        
        },
        inputField:{
            flex:1,
            height:42,
            padding:5,
            marginRight:25,
            borderRadius:5,
            borderWidth:1,
            borderColor:'rgba0,0,0,0.2',
            color:'#000000',
            fontSize:16,
            textAlignVertical:'center',   
        },
        addButton:{
            justifyContent:'center',
            alignItems:'center', 
            width:42,
            height:42,
            borderRadius:4,
            borderWidth:1,
            backgroundColor:'rgba0,0,0,0.7',
            shadowOpacity:0.14,
            shadowRadius:8,
            shadowOffset: {
                width: 0,
                height: 4,
            }
        },
        addButtonText:{
            color:'#000000',
            fontSize:25,
        },
    })

    위 코드를 사용해 스타일까지 어느정도 준 모습이다.

    안드로이드도 잘 나오고 아이폰도 잘 나온다

    할일 체크리스트 생성하기

    Pressable

    누르는 것의 여러가지 state를 감지할 수 있다 얼마나 누르느냐에 따라 다양한 event 설정

    핸드폰 화면은 작기때문에 체크박스의 조금 옆을 눌러도 체크되게 하는게 HitRect hitSlop

    이런식으로 지정해줄 수 있는 것

    PressRect

    터치를(혹은 클릭을)하고 있는 와중에도(활성화 되고 있는 와중에) 어느정도 거리까지 활성화가 될지를 정할 수 있는 것

     

    TodoItem.js

    import { Pressable, StyleSheet, Text, View } from 'react-native'
    import React from 'react'
    
    const TodoItem = () => {
      return (
        <View style={styles.itemContainer}>
            <Pressable
                style={styles.itemTextChecked}
                hitSlop={10}
            >
            </Pressable>
            <Text style={[styles.itemText, styles.itemTextChecked]}>
                코딩하기
            </Text>
            <Pressable 
                style={[
                    styles.deleteButton, styles.deleteButtonDone
                ]}
                hitSlop={10}
                >
            </Pressable>
          <Text>
    
          </Text>
        </View>
      )
    }
    
    export default TodoItem
    
    const styles = StyleSheet.create({})

    리엑트 네이티브에서 svg 사용

    리액트 네이티브는 svg 파일 지원을 안해서 모듈을 설치해야 한다.

    • react-native-svg
    npm install react-native-svg
    • react-native-svh-transformer
      임포트해서 사용하려면 이게 필요
    npm install -D react-native-svg-transformer

    metro.config.js 파일안에 넣어줄 코드가 있는데 npm웹사이트에서 확인이 가능하다.

    https://www.npmjs.com/package/react-native-svg-transformer 

     

    react-native-svg-transformer

    SVG transformer for react-native. Latest version: 1.0.0, last published: a year ago. Start using react-native-svg-transformer in your project by running `npm i react-native-svg-transformer`. There are 95 other projects in the npm registry using react-nativ

    www.npmjs.com

    프로젝트에 우클릭 New File을 해서 이름을 metro.config.js 로 지정해주고 아래 코드를 붙여넣기 한다.

    const { getDefaultConfig } = require("expo/metro-config");
    
    module.exports = (() => {
      const config = getDefaultConfig(__dirname);
    
      const { transformer, resolver } = config;
    
      config.transformer = {
        ...transformer,
        babelTransformerPath: require.resolve("react-native-svg-transformer"),
      };
      config.resolver = {
        ...resolver,
        assetExts: resolver.assetExts.filter((ext) => ext !== "svg"),
        sourceExts: [...resolver.sourceExts, "svg"],
      };
    
      return config;
    })();

    이제 svg 사용할 준비는 되어있는데 https://www.svgrepo.com/ 이곳에서 다운 받을 수 있다.

     

    다운 받은 파일들을 assets폴더에 넣어주고 이름에 맞춰 임포트도 해준다.

     

    import { Pressable, StyleSheet, Text, View } from 'react-native';
    import React from 'react';
    import checkboxIcon from '../assets/checkbox.svg';
    import checkboxCheckedIcon from '../assets/checkbox-checked.svg';
    import deleteIcon from '../assets/delete.svg';
    const TodoItem = () => {
      return (
        <View style={styles.itemContainer}>
            <Pressable
                style={styles.itemTextChecked}
                hitSlop={10}
            >
                <checkboxIcon />
                <checkboxCheckedIcon style={[styles.itemCheckboxCheckedIcon]} />
            </Pressable>
            <Text style={[styles.itemText, styles.itemTextChecked]}>
                코딩하기
            </Text>
            <Pressable 
                style={[
                    styles.deleteButton, styles.deleteButtonDone
                ]}
                hitSlop={10}
            >
                <deleteIcon />
            </Pressable>
          <Text>
    
          </Text>
        </View>
      )
    }
    
    export default TodoItem
    
    const styles = StyleSheet.create({})

    적용을 해 주고 실행을 하면 짜잔

    에러가 뜬다 - 버젼이 안맞는다 뭐라나 인데

    하란대로 해주자 터미널에 아래를 입력해 설치한다.

    npx expo install react-native-svg@13.4.0

    그리고 나서 다시 실행하고 R을 눌러 리로드를 해주면 

    나온다! 혹시 아이콘이 크게 나오면 svg 파일로 들어가 크기를 수정 할 수 있다.

    import { Pressable, StyleSheet, Text, View } from 'react-native';
    import React from 'react';
    import CheckboxUnchecked from '../assets/checkbox-unchecked.svg';
    import CheckboxChecked from '../assets/checkbox-checked.svg';
    import DeleteIcon from '../assets/delete.svg';
    const TodoItem = () => {
      return (
        <View style={styles.itemContainer}>
            <Pressable
                style={styles.itemCheckbox}
                hitSlop={10}
            >
                <CheckboxUnchecked />
                <CheckboxChecked style={[styles.itemCheckboxCheckedIcon]} />
            </Pressable>
            <Text style={[styles.itemText, styles.itemTextChecked]}>
                코딩하기
            </Text>
            <Pressable 
                style={[
                    styles.deleteButton, 
                    styles.deleteButtonDone
                ]}
                hitSlop={10}
            >
                <DeleteIcon />
            </Pressable>
          <Text>
    
          </Text>
        </View>
      )
    }
    
    export default TodoItem
        
    const styles = StyleSheet.create({
        itemContainer:{
            flexDirection: 'row',
            alignItems: 'center',
            paddingTop: 10,
            paddingBottom: 15,
            paddingHorizontal: 15,
            backgroundColor:'#f7f8fa',
        },
        itemCheckbox:{
            width: 20,
            height: 20,
            marginRight: 10,
            borderRadius: 5
        },
        itemCheckboxCheckedIcon:{
            shadowColor: 'black',
            shadowOpacity:0.14,
            shadoeRadius: 10,
            shadowOffset: {
                width: 0,
                height: 4
            },
        },
        itemText:{
            marginRight:'auto',
            paddingRight:'auto',
            fontsize:15,
            lineHeight:20,
            color:'#737373'
        },
        itemTextChecked:{
            opacity:0.3,
            textDecorationLine:'line-through'
        },
        deleteButton:{
            opacity:0.8
        },
        deleteButtonDone:{
            opacity:0.3
        }
    })

    대충 styles도 해줬고 결과

     

     

    여기까지 하고 다음번에 기능을 입혀보자

    728x90

    'React > React Native' 카테고리의 다른 글

    React Native 003  (0) 2022.12.30
    React Native 001  (0) 2022.12.27
    React Native 000  (0) 2022.12.26
designitlikesloth