재사용할 수 있는 조립 블록. 화면에 나타나는 UI요소이다.
객체 생성과 함수 호출을 위한 문법적 편의를 제공하기 위해 만들어진 확장 기능이다. 가독성이 높고, 작성하기 쉬우며 중첩 구조를 잘 나타낼 수 있다.
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내부에서는 간단하게 작성하는 것이 깔끔하다.
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>
);
}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>
);
}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
위 공식 문서에서 다양한 내장 컴포넌트를 확인할 수 있다.
<View>
<Text style={{ fontSize: 30, marginBottom: 10 }}>Button Component</Text>
<Button title="Button" onPress={() => alert('Click !!!')} />
</View>
이전에 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>
);
};
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보다 우선시된다.
MyButton.defaultProps = {
title: 'Button',
};
기본값을 자식 컴포넌트에서 지정할 수 있다.
잘못된 props가 전달되었을 때 PropTypes를 사용한다.
import PropTypes from 'prop-types';
...
MyButton.propTypes = {
title: PropTypes.number.isRequired,
};
propsType을 number로 지정해주었다. isRequired를 붙여주면 필수 전달 여부를 지정할 수 있다. propsType에는 이 외에도 string, func, object, array등이 있다.
컴포넌트 내부에서 생성되고 값을 변경할 수 있으며 컴포넌트 상태를 관리한다. 상태가 변하면 컴포넌트는 리렌더링한다.
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 = 자체 렌더링 엔진 + 위젯 트리 직접 재구성
→ 업데이트할 시점을 개발자가 알려줘야 함
→ 대신 성능이 매우 빠르고 일관적임
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는 사용자가 클릭하는 시간에 따라 둘 중에 하나만 호출된다.
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를 사용하면 더 간편하다. 컴포넌트의 텍스트가 변경되었을 때 변경된 텍스트의 문자열만 인수로 전달하며 호출된다.
기존의 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의 범위가 달라진다.