ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React Native Component
    React Native 2021. 1. 2. 12:13

    @ React Native 0.63 버전을 기반으로 작성했습니다.

    @ 모바일 플랫폼은 Android만 언급합니다.

    @ 최대한 쉽게 이해할 수 있도록 작성하려 노력했고 React 코드도 작성했습니다.

    @ 공식문서와 함께 보면 더 좋습니다.

    @ 0.63미만의 버전은 이 글과 내용이 다소 다를 수 있으니 참고해주세요.

    @ 편의상 세미콜론은 생략합니다.

    @ 오타가 있다면 알려주세요!

     

     

    리액트 네이티브는 리액트와 비교해서 무엇이 다를까? 

      React React Native
    공통점 hook공유, React 기반의 앱, 라이프사이클, Fragment 사용가능 등
    차이점 react-dom을 이용하여 dom을 구성
    웹에서만 동작하는 HTML 태그 사용
    react-native를 이용하여 구조를 만듬
    다양한 환경에서 동작해야 하므로 고유(native) 컴포넌트로 컴포넌트를 구성
    컴포넌트의 기본속성이 많이 다름(event)
    사용할 수 있는 스타일에 제한적(flex model)

    그러면 리액트 네이티브에서는 react를 쓰지 않는건가?

    그건 아니다

     

    웹에서 react는 react가 화면을 그려주는 것이 아니라 react-dom이 화면을 그려준다

    단지 react는 js에서 함수로 작성했을 때 jsx를 사용가능하게 해주고 hook을 사용할 수 있게 해준다.

    반면 RN에서는 RN자체가 JS브릿지, Native브릿지와 통신하여 화면을 그려준다. (@이 부분은 자세히 공부해봐야겠다.)

     

    @@ React를 하시던 분들이라면, 스타일은 React나 RN이나 비슷하니 넘어가시면 됩니다.

    또한 눈에 띄는 점은 css인데 스타일을 지정할 때에는

    예를 들면 웹에서는 background-color: 'red'; 를 사용하였지만

    RN에서는 { backgroundColor: 'red' }를 사용한다.

     

    // React
    
    import React from 'react';
    
    export default function App() {
      return (
        <div style="background-color: 'red';"></div>
      );
    }
    // React Native
    
    import React from 'react';
    import { View } from 'react-native';
    
    export default function App() {
      return (
        <View style={{ backgroundColor: 'red' }} />
      );
    }

     

    그러면 리액트 네이티브는 어떠한 컴포넌트들로 컴포넌트를 만드는걸까?

    이 글보다 더욱 풍부한 설명은 리액트 네이티브 공식 홈페이지 (링크)를 들어가서 Component를 들여다보자

     

    과거에 0.61, 0.62 버전이었을 때는 공식적으로 아래에 소개할 컴포넌트보다 훨씬 많은 컴포넌트들이 있었지만

    @react-native-community/어쩌고에 분리되었다.

    안타깝지만 라이브러리를 설치하면 그대로 사용할 수 있고 주기적으로 업데이트되니 걱정할 필요는 없다.

    당장 기억나는건 Slider, Picker 등이 있었다.

     

    크게 Core Component, Native Component 2가지 컴포넌트로 나뉜다.

     

    0] 들어가기 전에

    - 컴포넌트 네이밍 규칙

     

    React를 했던 사람들이라면 모두 알겠지만 혹여나 모르는 사람들이 있을 수 있으니 간략히 설명하자면

    컴포넌트의 이름은 제일 앞 글자는 무조건 대문자(Pascal Case)로 이름을 짓는다.

    그 이유는 웹 HTML태그를 짜는 경우에 <header>태그를 별도로 꾸며서 사용한다했을 때

    header 태그는 이미 있는 태그(웹 내장)이기 때문에 첫 글자는 대문자로 작성한다.

    그렇기 때문에 Header로 고쳐서 렌더링을 해야한다.

    RN도 마찬가지다 공식 문서에 있는 모든 컴포넌트들은 첫 글자는 대문자이다.

     

    1] Core Component

    코어 컴포넌트는 플랫폼에 관계없이 공통적으로 사용가능한 컴포넌트이다.

    대표적으로 View, Text, ActivityIndicator, TouchableHighlight, TouchableOpacity, Button, Modal, Image, FlatList, SectionList, ScrollView 등이 있다.

     

    각각 컴포넌트들은 React와 무엇이 다른지 비교해보자

     

     

     

    1) View

     

    <View>는 HTML에서 <div>와 유사하다.

     

      React React Native
    사용 태그 div View
    특징 display: block 등
    onClick ...
    기본 display값이 flex
    flex-direction: column
    View 컴포넌트 내에 다수의 컴포넌트 수용가능
    onClick이 존재하지 않음(ex: onPress)

    가장 큰 차이점은 기본 display 값이 flex라는 점이고 기본적으로 클릭 이벤트 같은 것들이 존재하지 않는다.

    또한 스타일에 있어서 타입이 존재한다.

    타입스크립트를 굳이 배우지 않아도 사용가능하지만 되도록이면 타입스크립트에 대한 약간의 개념은 있는 것이 좋다.

    공식문서도 parameter나 함수에 대한 타입을 모두 제공하기 때문이다

    그리고 스타일 타입은 해당 태그가 아닌 다른 컴포넌트의 옵션 속성에서도 사용이 가능하기 때문에 가급적이면 알아두는걸 추천한다.

     

    1} 스타일

    borderRadius같은 것들은 웹 스타일과 마찬가지로 여러 방향으로 지정이 가능하다.

    borderBottomLeftRadius, borderTopRightRadius를 지정하면 좌하단 우상단에만 radius를 적용할 수 있다.

    View 컴포넌트의 스타일 타입은 ViewProps이며 링크 에서 더 많이 볼 수 있다.

     

    @ View의 경우에 내용이 많아져서 화면 밖으로 나가면 스크롤바가 생기지도 않고 스크롤이 되지도 않으니 스크롤을 해야하는 상황이 오면 ScrollView를 쓰자

     

    2} 안드로이드 전용 props

    elevation - 어떠한 HTML에서 box가 있다고 할 때 이 박스에 shadow속성을 넣어주는 것과 동일하다.

    방향이나 색상을 별도로 지정할 수 없으며 depth만 지정가능하다.

    그리고 배경색상을 지정하지 않으면 elevation을 지정하더라도 효과가 나타나지 않으니 주의하자

     

    @ 0.63버전에서 업데이트

    명시적인 크기 지정없이 <View />로 작성이 가능하다

     

    2) Text

     

    HTML태그에서 p태그와 유사하다

    모든 일반 텍스트는 Text태그 안에 작성되어야 하며 그렇지 않은 경우에는 에러가 발생한다.

    Text내부의 텍스트는 생략이 가능하며 줄바꿈을 하는 경우에는 별도의 방법을 써야한다

     

    // React Native
    
    import React from 'react';
    import { Text } from 'react-native';
    
    export default function App() {
      return (
        // 기본 지정
        <Text>hello!</Text>
        
        // 줄바꿈 방법1: 같은 태그를 2번 연달아서 사용
        <Text>hello</Text>
        <Text>react native!</Text>
        
        // 줄바꿈 방법2: {'\n을 사용'}
        <Text>hello{'\n'} world!{</Text>
      );
    }

    1} 스타일

    View 컴포넌트와 마찬가지로 Text 태그에도 전용 스타일 타입이 있다. 링크

    Text Style Props에는 flex같은 너비와 관련된 것들은 지정할 수 없으나 margin은 적용이 가능하다.

    color, fontStyle, fontWeight, fontSize, lineHeight 등이 있으며

    lineHeight의 경우에는 웹에서 사용하던 방식과 같이 1.5를 주면 글자가 겹쳐진다.

    간격을 넓히고자 할 때에는 글자의 fontSize보다 크게 주면 된다.

    웹에서의 text-decoration => textDecorationStyle을 사용하여 취소선 등을 장식할 수도 있다.

     

    @ 0.63버전에서 업데이트

    명시적인 크기 지정없이 <Text />로 작성이 가능하다

     

     

    3) ActivityIndicator

     

    이 컴포넌트는 흔히 로딩 중일 때 뱅글뱅글 돌아가는 원형 ProgressBar 이다.

    // React Native
    
    import React from 'react';
    import { ActivityIndicator } from 'react-native';
    
    export default function App() {
      return (
        <ActivityIndicator size="large" color="#ff0000" />
      );
    }

    이러한 ProgressBar(ProgressBar 라고 하겠다)를 웹에서 사용하려면 별도의 라이브러리를 이용하거나 직접 구현해야 했지만 리액트 네이티브에서는 기본으로 제공한다.

     

    props에는 size color animating 등이 있으며 size에는 'large', 'small'이 있고 color는 아무 색상이나 지정이 가능하다.

    안드로이드는 사이즈를 숫자로도 지정 가능

     

    이 컴포넌트는 animating속성 기본값이 true이기 때문에 별도로 멈춰주거나 숨김처리를 하지 않는 한 무한정으로 돌아간다.

     

     

     

    4) Modal

     

    웹에서 Modal을 구현하려면 div태그 등을 이용하여 한 번 더 감싸주고 배경색을 어둡게 설정하여 구현한다.

    리액트 네이티브에서는 이 역할을 하는 컴포넌트를 기본으로 제공하는데 그것이 바로 Modal 컴포넌트이다.

    단 기본적으로 색상이 어둡지 않기 때문에 Modal 내부에 View 컴포넌트를 넣고 너비, 높이를 적당히 조절해서 View 컴포넌트의 배경색을 어둡게 하면 되겠다. 어둡게 사용하지 않으려면 굳이 지정하지 않아도 된다.

     

    // React Native
    
    import React, { useState } from 'react';
    import { Modal, View, Keyboard } from 'react-native';
    
    export default function App() {
      const [visible, setVisible] = useState(true)
    
      return (
        <Modal
          visible={visible} // Modal을 보여줄건지 보여주지 않을건지 설정, true이면 보여준다
          animationType='slide' // slide로 설정하면 위에서 아래로 나오고 이 외에 'fade', 'none'이 있다
          hardwareAccelerated // 하드웨어 가속을 할 것인지 설정한다
          
          // modal이 해제되면 보여줄 함수를 전달할 수 있으며 모달이 나타났을 때 키보드를 숨김처리한다
          onDismiss={Keyboard.dismiss} 
          
          // 뒤로가기 버튼을 눌렀을 때 닫힐 것인지 설정하는 함수이다.
          // Modal에서는 BackHandler API가 적용되지 않으므로 이 props를 써야한다.
          onRequestClose={() => setVisible(false)}
          
          // Modal이 나왔을 때 statusbar 위에 보여줄 건지 아래에 보여줄건지 설정, true이면 아래에서 보여준다
          statusBarTranslucent
        >
          <View>
            <Text>Modal!!</Text>
            <Button title='close' onPress={() => setVisible(false)} />
          </View>
        </Modal>
      );
    }

     

     

    5) Image

     

    웹 img 태그와 유사하다. 다만 다른점은 src속성이 아닌 source를 사용하고 그 안에 객체를 넣어야 하며 키 이름은 uri다

    또한 너비와 높이를 지정해주지 않으면 이미지가 표시되지 않으니 아래의 코드를 참고하여 작성해보자

    // React Native
    
    import React from 'react';
    import { Image } from 'react-native';
    
    export default function App() {
      const src = 'http://example.com/cat1.jpg'
      
      return (
        // 너비와 높이를 지정하는 방법은 2가지가 있으니 아무렇게나 해도 상관없다.
        // 다만 무조건 지정해줘야 이미지가 표시됨
        
        // 방법1: require를 이용하여 uri 등록
        <Image source={{ uri: require('../assets/cat2.jpg') }} style={{ width: 100, height: 100 }} />
        
        // 방법2: uri를 직접 등록
        <Image source={{ uri: src }} width={100} height={100} />
      );
    }

     

    6) ImageBackground

     

    이 태그를 사용하면서 느낀 것은 어떠한 div 태그에 background-image 속성을 준 컴포넌트라고 생각했다.

    이름에서도 알 수 있다시피 백그라운드 이미지를 설정하는 컴포넌트이다.

    여러 개를 사용해도 해당 하위 컴포넌트가 차지하는 content만큼 작용한다

     

    내부의 이미지에 접근할 수 있는 imageRef도 있으나 딱히 써본 적이 없는 것 같다.

     

    // React Native
    
    import React, { useState } from 'react';
    import { ImageBackground, View, Text } from 'react-native';
    
    export default function App() {
      const uri = 'http://example.com/tiger.png';
    
      return (
        <View>
          <ImageBackground 
            source={{ uri }}
            imageStyle={{ width: 100 }} // image prop Style 타입 (ImageBackground 안에서 렌더링될 이미지 사이즈 설정)
            style={{ flex: 1 }} // View Prop Style (ImageBackground의 너비 높이를 설정한다고 생각하면 되겠다)
          > // Text에만 background 설정
            <Text>Modal!!</Text>
          </ImageBackground>
        </View>
      );
    }

     

     

    7) FlatList

     

    FlatList 컴포넌트는 어떠한 데이터를 받아서 표현해줄 컴포넌트에 맞게 출력해주며 스크롤을 가진다.

     

    // React
    
    import React from 'react';
    
    export default function App() {
      const arr = [1, 2, 3, 4, 5]
      
      return (
        <div>
          {arr.map((element, index) => <p key={index}>{element}</p>)}
        </div>
      );
    }
    
    // React에서는 css를 지정하는 경우를 제외하고
    // 일정 너비, 높이가 넘어가지 않는 이상 브라우저에 스크롤이 생기지 않는다
    
    // map을 사용하는 경우에는 반드시 key prop을 지정해줘야 한다

     

    // React Native
    
    import React, { useState } from 'react';
    import { FlatList, Text, View } from 'react-native';
    
    export default function App() {
      const [refresh, setRefresh] = useState(false)
      const ref = useRef(null)
      
      const onEnd = () => {
        if (ref.current !== null) {
          ref.current.scrollToEnd() // FlatList의 가장 아래로 스크롤
          ref.current.scrollToEnd({animated: false})
        }
      }
      
      const data = [1, 2, 3, 4, 5]
    
      return (
        <View>
          <FlatList
            ref={ref}
            
            // 반복해서 보여줄 데이터, React에서 치면 map을 할 데이터
            data={data}
            
            // 데이터를 반복해서 보여줬을 때 보여질 컴포넌트
            renderItem={({ item, index }) => <Text>{item}</Text>}
            
            // key 속성
            keyExtractor={(item, index) => index}
            
            horizontal // 수평 방향으로 나열할건지?
            showsVerticalScrollIndicator={false} // 수직 방향 스크롤바를 보여줄건지?
            showsHorizontalScrollIndicator // 수평 방향 스크롤바를 보여줄건지?
            
            // 휴대폰 화면에서 스크롤이 최상으로 올라갔을 때
            // 한 번 더 쭉 내려주면 새로고침할건지?
            refreshing={refresh}
            onRefresh={() => {
              console.log('새로고침!')
              setRefresh(false)
            }}
            
            // 마치 section처럼 보여지는 prop이지만 최상위에 딱 한 번만 나온다
            ListHeaderComponent={() => <Text>number is...</Text>}
            
            // ViewProp 속성이고 ListHeaderComponent를 감싸는 가상의 View의 스타일
            ListHeaderComponentStyle={{ width: 100 }}
            
            numColumns={2} // 2열로 Grid화하고 지정하지 않으면 1열
            scrollEnabeld // 스크롤 가능하게 할건지? 기본값은 true, false이면 스크롤하지 않음
          />
        </View>
      );
    }
    
    // React에서는 map을 했을 때 보여질 컴포넌트의 최상위 태그에 key속성을 부여했었어야 했지만
    // React Native에서는 대신 keyExtractor로 key속성을 대신한다
    
    // 공식문서 외에 IDE에 표시되는 것들도 있으니 참고

     

     

    8) SectionList

     

    FlatList와 유사하며 차이점은 마치 <section>태그를 쓰는 것과 같이 각 section에 제목이 설정된다.

     

    9) ScrollView

     

    FlatList, SectionList와 마찬가지로 스크롤을 할 수 있는 View 태그이다.

    다만 data를 이용하여 map을 한 것처럼 여러 개를 한 번에 나열하는 기능은 없다.

     

    // React Native
    
    import React from 'react';
    import { ScrollView, View, Text } from 'react-native';
    
    export default function App() {
      return (
        <ScrollView
          scrollEnabled
          keyboardDismissMode='on-drag' // 키보드를 숨김처리할건지? 기본값은 none
          horizontal // 가로로 나열할건지?
          showsVerticalScrollIndicator={false} // 수직 방향 스크롤바를 보여줄건지? 보여주지 않아도 스크롤 가능
          showsHorizontalScrollIndicator // 수평 방향 스크롤바를 보여줄건지? 기본값 true
        >
          <View>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
            <Text>React Native!</Text>
          </View>
        </ScrollView>
      );
    }
    
    // 배열에 넣고 map을 하는 방법도 있지만 더 쉽게 알 수 있도록 Text를 많이 나열했다

     

    - 그렇다면 FlatList와  ScrollView에는 어떤 것을 써야하는걸까?

    내용을 한 번에 렌더링해서 보여주려면 ScrollView를 사용하고 그렇지 않으면 FlatList를 쓰는 것이 좋다.

    공식문서 설명에 따르면 ScrollView의 경우에는 성능저하가 있을 수도 있다고 한다.

     

    10) Button

     

    말 그대로 버튼 컴포넌트인데 차이점이 좀 있다.

     

    <!-- HTML에서는 태그 사이에 내용을 채운다 -->
    <button>click me!</button>

    1. Button 컴포넌트는 title과 onPress가 필수속성이며 닫는 태그가 없다

    2. 닫는 태그가 없기 때문에 title 속성에다 버튼의 이름을 지정해주어야 하며 영어인 경우 대문자로 바뀌어서 출력된다

    3. onPress는 눌렀을 때 무슨 작업을 할 것인지 지정하는 함수를 넣어주면 된다.

    4. 버튼은 flex: 1처럼 너비가 100%이기 때문에 너비를 조정해주려면 View 같은 태그로 감싸서 View의 너비를 조정해주면 된다

    5. 안드로이드는 배경색상이 #2196F3, 글자색상이 흰색이며 ios는 #007AFF으로 글자색상이 설정된다

    6. 5번의 색상을 변경하려면 color props를 지정하면 된다 또는 color API활용

    7. disabled는 버튼을 활성화할 것인지 하지 않을 것인지의 boolean값을 넣어주면 된다.

    8. 자식 컴포넌트를 가질 수 없음!

     

    다음은 버튼을 누르면 console에 'click!'이라고 표시되는 컴포넌트이다

    // React Native
    
    import React from 'react';
    import { Button } from 'react-native';
    
    export default function App() {
      return (
        <Button onPress={() => console.log('click!')} title='click me' />
      );
    }

     

    11) Switch

     

    수평방향으로 움직여서 전자기기를 켜는 그 스위치와 동일하다.

    // React Native
    
    import React, { useState } from 'react';
    import { View, Button, Switch } from 'react-native';
    
    export default function App() {
      const [on, setOn] = useState(false)
    
      return (
        <View>
          <Button onPress={() => console.log('click!')} title='click me' />
          <Switch
            disabled={false} // 스위치 사용가능 여부 지정
            onChange{e => console.log(e)}
            onValueChange={value => setOn(!value)} // 스위치를 켜고 끄는 함수
            thumbColor='#414265' // 스위치 단추의 색상 지정
            trankColor={{ true: 'red', false: 'yellow' }} // 스위치를 켜고 끌 때 뒷배경의 색상, true이면 false쪽에 색상이 'red'
          />
        </View>
      );
    }

     

    12) TextInput

     

    TextInput은 HTML에서 input과 동일하다

    Change 이벤트가 발생하면 input 태그에서는 onChange를 썼지만

    TextInput에서 onChange의 이벤트 객체 안에는 공식문서에 따르면 { nativeEvent: { eventCount, target, text} }이 들어있다.

    input 태그에서 간편하게 썼던 onChange와 비교하면 연산자가 더 들어가는 셈이다.

    그를 위해서 onChangeText라는 props가 생겼다.

     

    // React
    
    import React, { useState } from 'react';
    
    export default function App() {
      const [text, setText] = useState('')
      
      return (
        <div>
          <input value={text} onChange={(event) => setText(event.target.value)} />
        </div>
      );
    }

     

    // React Native
    
    import React, { useState } from 'react';
    import { View, TextInput } from 'react-native';
    
    export default function App() {
      const [text, setText] = useState('')
      
      return (
        <View>
          <TextInput value={text} onChangeText={(letter) => setText(letter)} />
        </View>
      );
    }

     

    13) TouchableHighlight

    14) TouchableOpacity

    15) TouchableWithoutFeedback

    16) Pressable (0.63에서 업데이트된 컴포넌트)

    @ Native Component의 TouchableNativeFeedback과 같이 설명

    2] Native Component

     

    iOS기기를 가지고 있지 않아서 정확히 어떠한 효과를 지니는지 알지 못해서 안드로이드만 소개해보려 한다

     

    1) DrawerLayoutAndroid

     

    이 컴포넌트는 휴대폰의 왼쪽 또는 오른쪽 끝에서 가로방향으로 드래그 (이 행위를 swipe라고 한다)했을 때 옆에서 창이 slide로 나오는 것을 의미한다

     

    또한 swipe를 했을 때 slide해주는 별도의 메서드도 있으며 사용은 보통 ref를 이용한다.

     

    // React Native
    
    import React, { useRef } from 'react';
    import { DrawerLayoutAndroid, View, Text, Button } from 'react-native';
    
    const DrawerView = () => (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>Drawer!</Text>
          <Button
            title="close"
            onPress={() => drawer.current.closeDrawer()}
          />
        </View>
      );
    
    export default function App() {
      const ref = useRef(null)
      
      const onDraw = () => {
        if (ref.current !== null) {
          ref.current.openDrawer()
        }
      }
      
      const onDrawOut = () => {
        if (ref.current !== null) {
          ref.current.closeDrawer()
        }
      }
    
      return (
        // 최상위 컴포넌트를 DrawerLayoutAndroid로 감싸주자
        <DrawerLayoutAndroid
          // 슬라이드되었을 때 표시할 너비
          drawerWidth={300}
          
          ref={ref}
          
          // drawerPosition => left, right지정가능하며 right이면 오른쪽에서 왼쪽으로 나온다
          drawerPosition='right'
          
          // renderNavigationView => 화면에서 보여줄 컴포넌트
          renderNavigationView={DrawerView}
          
          // 별도의 컴포넌트를 지정하지 않아도 되며 JSX만 반환한다면 아래와 같이 작성해도 문제없다.
          // renderNavigationView={() => <View><Text>Drawer!</Text></View>}
          
          // 별도의 props도 넣어주고 싶다면
          // renderNavigationView={() => <DrawerView onPress={onDrawOut} />}
        >
          <View>
            <Button title='open' onPress={onDraw} />
          </View>
        </DrawerLayoutAndroid>
      );
    }

    DrawerLayoutAndroid에서 한 번 나오고 난 이후로 계속 고정할 수 있다.

    drawerLockMode라는 것을 props에 넣어주면 되는데 기본값은 'unlocked'이다

    'locked-closed' 로 설정하면 닫히고 나서 어떠한 행동을 취해도 열리지 않음

    'locked-open'으로 설정하면 열리고 나서 어떠한 행동을 취해도 닫히지 않음

     

    onDrawerClose, onDrawerOpen props를 통해서 닫히고 열리고 나서 난 뒤 어떠한 작업을 할지 결정할 수도 있다

     

     

    2) TouchableNativeFeedback

     

    Core 컴포넌트인 TouchableHighlight, TouchableOpacity, TouchableWithoutFeedback, Pressable과

    Native 컴포넌트 TouchableNativeFeedback의 공통점은 누를 수 있는 버튼이다.

    그런데 왜 Button과 달리 설명하는가? 라고 물어볼 수 있을텐데 Button 컴포넌트는 자식 컴포넌트를 가질 수 없다

    반면 Touchable접두사가 붙은 컴포넌트와 Pressable은 자식을 가질 수 있다.

     

    먼저 Pressable은 버튼에 손을 갖다대고 누른 상태, 길게 누른 상태, 버튼이 눌러진 상태에서 손을 뗀 상태에 따라서 

    여러 작업이 가능하다. 여러 개의 자식 컴포넌트를 가질 수 있다.

    // React Native
    
    import React, { useState } from 'react';
    import { Pressable, Text, View } from 'react-native';
    
    const App = () => {
      const [count, setCount] = useState(0);
    
      return (
        <View>
          <Pressable 
            onPress={() => setCount(prev => prev + 1)} // 짧게 누른 경우
            onLongPress={() => console.log('길게 누르셨어요!')} // 길게 누른 경우(통상 500ms 이상)
            onPressOut={() => console.log('눌렀다 뗐어요~')} // 손가락이 휴대폰 액정에서 떨어진 순간
            onPressIn={() => console.log('무언가 저에게 닿았어요')} // 손가락으로 누른 순간
          >
            {
              ({ pressed }) => (
                <Text>
                  {pressed ? `${count}번 눌렸음!` : '누르지 않은 상태!'}
                </Text>
              )
            }
          </Pressable>
        </View>
      );
    };

    Touchable접두사가 붙은 컴포넌트들은 Pressable 컴포넌트와 다르게 자식 컴포넌트를 단 1개밖에 가질 수 없다.

    자식 컴포넌트가 1개보다 많다면 에러가 발생한다.

    또한 Touchable 컴포넌트들의 크게 다른 점은 눌렀을 때의 효과가 제각각 다르다.

    // React Native
    
    import React, { useState } from 'react';
    import {
      Text, 
      View, 
      TouchableNativeFeedback, 
      TouchableHighlight, 
      TouchableOpacity, 
      TouchableWithoutFeedback,
    } from 'react-native';
    
    const App = () => {
      return (
        <View>
          // TouchableNativeFeedback(안드로이드 전용)
          // => 눌렀을 때 살짝 밝은 회색이 가운데서부터 바깥으로 퍼진다.
          <TouchableNativeFeedback onPress={() => console.log('TouchableNativeFeedback')}>
            <View>
              <Text>react</Text>
              <Text>native</Text>
            </View>
          </TouchableNativeFeedback>
          // => 이 컴포넌트는 에러가 발생하지 않음, 자손이 아닌 자식이 1개이기 때문
          
          // TouchableWithoutFeedback: 눌러도 아무런 효과가 없다.
          <TouchableWithoutFeedback onPress={() => console.log('TouchableNativeFeedback')}>
            <View>
              <Text>react native</Text>
            </View>
            <View>
              <Text>react native</Text>
            </View>
          </TouchableWithoutFeedback>
          // 이 컴포넌트는 에러! 자식 컴포넌트가 1개보다 많기 때문에 에러가 발생한다.
          
          // TouchableHighlight: 눌렀을 때 버튼의 색상이 전체적으로 다른 색상으로 바뀜
          <TouchableHighlight onPress={() => console.log('TouchableHighlight')}>
            <View>
              <Text>react native</Text>
            </View>
          </TouchableHighlight>
          
          // TouchableOpacity: 눌렀을 때 버튼의 색상이 불투명하게 바뀜
          <TouchableOpacity 
            onPress={() => console.log('TouchableOpacity') 
            onLongPress={() => console.log('Long TouchableOpacity')}}
          >
            <View>
              <Text>react native</Text>
            </View>
          </TouchableOpacity>
        </View>
      );
    };
    
    export default App;

     

     

    @@@@@

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

    React Native 새로운 아키텍처  (0) 2021.01.18
    React Native Android API  (0) 2021.01.02

    댓글

Designed by Tistory.