[처음부터 배우는 리액트 네이티브]컴포넌트

최다연·2025년 11월 13일

ReactNative

목록 보기
1/8

컴포넌트

재사용할 수 있는 조립 블록. 화면에 나타나는 UI요소이다.

JSX

객체 생성과 함수 호출을 위한 문법적 편의를 제공하기 위해 만들어진 확장 기능이다. 가독성이 높고, 작성하기 쉬우며 중첩 구조를 잘 나타낼 수 있다.

여러개의 요소를 표현할 경우 하나의 부모로 감싸야 한다.

  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );

여러개의 요소를 반환하고 있어 View태그로 묶어주었다. View는 div태그와 비슷한 역할을 한다. View는 화면에 보이는 레이아웃 요소이다. 단순히 여러개의 컴포넌트를 반환하고 싶은 경우 Fragment컴포넌트를 사용한다. 로 사용해도 되고 <></>로 단축 문법을 사용해도 된다.

내부에서 자바스크립트 변수를 전달하여 이용

export default function App() {
  const name = 'Dayeon';
  return (
    <View style={styles.container}>
      <Text style={styles.text}>My name is {name}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

자바스크립트 조건문

조건에 따라 나타나는 요소를 다르게 하고 싶을 때 JSX에서 조건문을 사용할 수 있다. 다만 제약 조건이 있어 밖에서 조건에 따른 값을 설정하고 JSX내부에서는 간단하게 작성하는 것이 깔끔하다.

  • if문
    const name = 'Dayeon';
    return (
      <View style={styles.container}>
        <Text style={styles.text}>
          {(() => {
            if (name === 'Hanbit') return 'My name is Hanbit';
            else if (name === 'Dayeon') return 'My name is Dayeon';
            else return 'My name is React Native';
          })()}
        </Text>
        <StatusBar style="auto" />
      </View>
    );
  • 삼항연산자
    export default function App() {
      const name = 'Dayeon';
      return (
        <View style={styles.container}>
          <Text style={styles.text}>
            My name is {name === 'Dayeon' ? 'Dayeon Choi' : 'React Native'}
          </Text>
          <StatusBar style="auto" />
        </View>
      );
    }
  • AND, OR연산자
    export default function App() {
      const name = 'Dayeon';
      return (
        <View style={styles.container}>
          {name === 'Dayeon' && (
            <Text style={styles.text}>My name is Dayeon</Text>
          )}
          {name !== 'Dayeon' && (
            <Text style={styles.text}>My name is not Dayeon</Text>
          )}
          <StatusBar style="auto" />
        </View>
      );
    }
  • null과 undefined null은 허용하지만 undefined는 허용하지 않는다
  • 주석 JSX의 주석은 {/* /}을 사용한다. 단, 태그 안에서는 // 나 / */를 사용한다.
  • 스타일링 HTML과 달리 객체 형태로 입력해야 한다. 그리고 하이픈으로 연결된 이름은 카멜표기법으로 바꾸어 작성해야한다.
    const App = () => {
      return (
        <View
          style={{
            flex: 1,
            backgroundColor: '#fff',
            alignItems: 'center',
            justifyContent: 'center',
          }}
        >Text>Open up App.js to start working on your app!</Text>
        </View>
      );
    };

컴포넌트

Core Components and APIs · React Native

위 공식 문서에서 다양한 내장 컴포넌트를 확인할 수 있다.

Button 컴포넌트 예시

<View>
  <Text style={{ fontSize: 30, marginBottom: 10 }}>Button Component</Text>
  <Button title="Button" onPress={() => alert('Click !!!')} />
</View>
  • title 속성: 버튼 내부에 출력되는 텍스트
  • onPress 속성: 버튼이 눌렸을 때 호출되는 함수
  • color: ios에서는 텍스트 색상, android에서는 바탕색

이전에 Flutter를 할 때에는 모든 플랫폼에 동일하게 적용되었었는데, RN은 아니라고 하여 그 이유를 찾아보았다. Flutter는 자체적인 엔진(Skia)을 사용하지만 RN은 네이티브의 위젯을 가져와 사용해서 OS별로 다르게 나올 수 있다고 한다.

커스텀 컴포넌트 만들기

여러 내장 컴포넌트를 조합하여 새로운 컴포넌트를 만들 수 있다.

import React from 'react';
/*리액트를 불러옴*/
import { TouchableOpacity, Text } from 'react-native';
/*RN에서 제공하는 TouchableOpacity, Text컴포넌트 추가*/
const MyButton = () => {
  return (
    <TouchableOpacity/*클릭에 대해 상호작용 할 수 있도록 함*/
      onPress={() => alert('Click !!!')}
    >
      <Text style={{ fontSize: 24 }}>My Button</Text>
    </TouchableOpacity>
  );
};

props와 state

props

properties를 줄인 표현으로 부모 컴포넌트로부터 전달된 속성값 혹은 상속받은 속성값을 말한다. 부모로부터 받은 props를 사용할수는 있지만 변경은 불가능하다.

<MyButton title="Button" />
/*MyButton 컴포넌트에게 title이라는 이름의 데이터를 넘긴다*/
const MyButton = props => {
  return (
    <TouchableOpacity>
      <Text style={{ color: 'white', fontSize: 24 }}>
        {props.title} /*props를 전달받아 출력*/
      </Text>
    </TouchableOpacity>
  );
};

컴포넌트 태그 사이에 값을 입력하여 전달할 수도 있다

<MyButton title="Button">Children Props</MyButton>
const MyButton = props => {
  return (
    <TouchableOpacity>
      <Text style={{ color: 'white', fontSize: 24 }}>
        {props.children || props.title}
      </Text>
    </TouchableOpacity>
  );
};

태그 사이로 전달된 값은 children으로 전달된다. props에 children이 있다면 title보다 우선시된다.

defaultProps

MyButton.defaultProps = {
  title: 'Button',
};

기본값을 자식 컴포넌트에서 지정할 수 있다.

propTypes

잘못된 props가 전달되었을 때 PropTypes를 사용한다.

import PropTypes from 'prop-types';

...

MyButton.propTypes = {
  title: PropTypes.number.isRequired,
};

propsType을 number로 지정해주었다. isRequired를 붙여주면 필수 전달 여부를 지정할 수 있다. propsType에는 이 외에도 string, func, object, array등이 있다.

state

컴포넌트 내부에서 생성되고 값을 변경할 수 있으며 컴포넌트 상태를 관리한다. 상태가 변하면 컴포넌트는 리렌더링한다.

  • useState 함수형 컴포넌트에서 상태를 관리할 수 있도록 해준다.
    import React, { useState } from 'react';
    import { View, Text } from 'react-native';
    import MyButton from './MyButton';
    
    const Counter = () => {
      const [count, setCount] = useState(0);
      /*상태 관리 변수와 변수를 변경할 수 있는 세터 함수를 배열로 반환, 0으로 초깃값 설정*/
      return (
        <View style={{ alignItems: 'center' }}>
          <MyButton
            title="+"
            onPress={() => {
              setCount(count + 1); /*버튼을 누르면 count +1*/
            }
          />
          <MyButton
            title="-"
            onPress={() => {
              setCount(count - 1); /*버튼을 누르면 count -1*/
            }
          />
        </View>
      );
    };
    
    export default Counter;
    useState는 여러개일 수 있다. 관리해야 하는 상태의 수만큼 useState를 사용한다.

React Native = 선언적(Declarative) UI + Virtual DOM 기반
→ 상태가 변하면 React가 “무엇을 다시 그릴지” 판단
→ 개발자는 신경 안 써도 됨

Flutter = 자체 렌더링 엔진 + 위젯 트리 직접 재구성
→ 업데이트할 시점을 개발자가 알려줘야 함
→ 대신 성능이 매우 빠르고 일관적임

이벤트

press이벤트

onClick이벤트와 비슷한 이벤트이다. TouchableOpacity 컴포넌트에서 설정할 수 있는 press 이벤트의 종류는 4가지이다.

  • onPressln: 터치가 시작될 때 항상 호출
  • onPressOut: 터치가 해제될 때 항상 호출
  • onPress: 터치가 해제될 때 onPressOut 이후 호출
  • onLongPress: 터치가 일정 시간 이상 지속되면 호출
import React from 'react';
import { TouchableOpacity, Text } from 'react-native';

const EventButton = () => {
  const _onPressIn = () => console.log('Press In !!!\n');
  const _onPressOut = () => console.log('Press Out !!!\n');
  const _onPress = () => console.log('Press !!!\n');
  const _onLongPress = () => console.log('Long Press !!!\n');

  return (
    <TouchableOpacity
      style={{
        backgroundColor: '#f1c40f',
        padding: 16,
        margin: 10,
        borderRadius: 8,
      }}
      onPressIn={_onPressIn}
      onLongPress={_onLongPress}
      onPressOut={_onPressOut}
      onPress={_onPress}
      delayLongPress={3000}/*onLongPress호출 시간 조절*/
    >
      <Text style={{ color: 'white', fontSize: 24 }}>Press</Text>
    </TouchableOpacity>
  );
};

export default EventButton;

onPress와 onLongPress는 사용자가 클릭하는 시간에 따라 둘 중에 하나만 호출된다.

change 이벤트

import React, { useState } from 'react';
import { View, Text, TextInput } from 'react-native';

const EventInput = () => {
  const [text, setText] = useState('');
  const _onChange = event => setText(event.nativeEvent.text);

  return (
    <View>
      <Text style={{ margin: 10, fontSize: 30 }}>text: {text}</Text>
      <TextInput
        style={{ borderWidth: 1, padding: 10, fontSize: 20 }}
        placeholder="Enter a text..."
        onChange={_onChange}/*TextInput컴포넌트에 입력된 텍스트가 변경될 때 호출*/
      />
    </View>
  );
};

export default EventInput;

위와 같이 텍스트만 변화될 경우 onChangeText를 사용하면 더 간편하다. 컴포넌트의 텍스트가 변경되었을 때 변경된 텍스트의 문자열만 인수로 전달하며 호출된다.

Pressable컴포넌트

기존의 TouchableOpacity 컴포넌트를 대체하는 Pressable 컴포넌트이다. 기존의 컴포넌트보다 더 다양한 기능을 제공한다.

import React from 'react';
import { View, Text, Pressable } from 'react-native';

const Button = (props) => {
  return (
    <Pressable
      style={{ padding: 10, backgroundColor: '#1abc9c' }}
      onPressIn={() => console.log('Press In')}
      onPressOut={() => console.log('Press Out')}
      onPress={() => console.log('Press')}
      onLongPress={() => console.log('Long Press')}
      delayLongPress={3000}
      pressRetentionOffset={{ bottom: 50, left: 50, right: 50, top: 50 }}
      hitSlop={50}
    >
      <Text style={{ padding: 10, fontSize: 30 }}>{props.title}</Text>
    </Pressable>
  );
};

const App = () => {
  return (
    <View
      style={{
        flex: 1,
        justifyContent: 'center',
        backgroundColor: '#fff',
        alignItems: 'center',
      }}>
      <Button title="Pressable" />
    </View>
  );
};

export default App;

HitRect와 PressRect를 이용하여 이벤트 발생 범위를 조절할 수 있다. hitSlop값에 따라 PressRect의 범위가 달라진다.

0개의 댓글