React Native 기초(공식문서 가이드 보기)
React
- 프로젝트 생성 :
react-native init [프로젝트명]
- Android 실행 :
npm run android
공식문서를 보면서 정리한 내용
일단 공식문서
React Native
React Native는 React와 비슷하지만 web component 대신 native component를 사용한다.
왜 항상 import React from 'react';
이걸 해야할까?
JSX를 사용하려면 React를 가져와야 한다는데 왜그러지.
props 받는 방법
import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
center: {
alignItems: 'center'
}
})
const Greeting = (props) => {
return (
<View style={styles.center}>
<Text>Hello {props.name}!</Text>
</View>
);
}
const LotsOfGreetings = () => {
return (
<View style={[styles.center, {top: 50}]}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
export default LotsOfGreetings;
State
import React, { Component } from 'react'
import {
StyleSheet,
TouchableOpacity,
Text,
View,
} from 'react-native'
class App extends Component {
state = {
count: 0
}
onPress = () => {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={this.onPress}
>
<Text>Click me</Text>
</TouchableOpacity>
<View>
<Text>
You clicked { this.state.count } times
</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
marginBottom: 10
}
})
export default App;
Layout
React는 Flexbox 알고리즘을 사용하여 Layout을 구성할 수 있다. Flexbox가 뭐지..
Flexbox는 웹의 CSS에서와 동일한 방식으로 React Native에서 작동하지만 몇 가지 예외가 있습니다. 기본값은 함께 다른 flexDirection을 디폴트 column대신에 row, 상기 flex매개 변수는 하나의 숫자를 지원.
Flex
Flex는 Component의 기본속성이다. Flax에는 내용은 기본 축을 따라 사용 가능한 공간을 어떻게 채울지 정의한다.
빨간색은 flex: 1
, 노란색은 flex: 2
,녹색은은 flex:3
이라고 적었을 때
각각 총 합계에서 퍼센트 만큼 크기를 차지한다.
빨간색은 1/6, 노란색은 2/6,녹색은은 3/6을 차지하게 된다.
Flex 방향
flexDirection이라는 속성이 있다. 이 속성으로 오른쪽 왼쪽 위 아래 방향을 제어할 수 있다. 설정값은 여기를 보면 된다.
import React from 'react';
import { View } from 'react-native';
const FlexDirectionBasics = () => {
return (
// Try setting `flexDirection` to `column`.
<View style={{flex: 1, flexDirection: 'column-reverse'}}>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>
);
};
export default FlexDirectionBasics;
레이아웃 방향
레이아웃 방향은 계측 구조에서 자식 및 텍스틍가 배치되는 방향을 지정한다. React Native에서 레이아웃 방향은 설정값은 다음과 같다.
LTR
: 기본값 왼쪽에서부터 오른쪽으로 배치RTL
오른쪽에서 왼쪽으로 배치
레이아웃 방향을 설정하는 방법은 여러가지가 있다.
-
justifyContent :
설정 방법은 여기에 있고 기본값은 왼쪽 시작줄에 맞춥니다.import React from 'react'; import { View } from 'react-native'; const JustifyContentBasics = () => { return ( // Try setting `justifyContent` to `center`. // Try setting `flexDirection` to `row`. <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'space-between', }}> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} /> </View> ); }; export default JustifyContentBasics;
-
alignItems : 가로 축을 따라 정렬하는 방법이다.
- stretch( default value ) height컨테이너의 가로 축 과 일치하도록 컨테이너의 자식을 늘 립니다.
- flex-start 컨테이너의 자식을 컨테이너의 가로 축 시작에 맞 춥니 다.
- flex-end 컨테이너의 자식을 컨테이너의 가로 축 끝에 맞 춥니 다.
- center 컨테이너의 자식을 컨테이너의 가로 축 가운데에 맞 춥니 다.
- baseline공통 기준선을 따라 컨테이너의 자식을 정렬합니다. 개별 아동을 부모의 기준선으로 설정할 수 있습니다.
그외에도 많지만 https://reactnative.dev/docs/flexbox 공식 가이드 가서 봐도 되고 yogalayout.com이라는 곳 가서 만져봐도 좋다.
Components
Component는 App 개발에 있어서 핵심이 되는 것이다. 컴포넌트로 App의 유저에서 보여지는 것들 혹은 그외것들을 만들 수 있다. 여기에 가면 기본 Component이 나온다.
Navigating (화면 탐색)
모바일에서는 하나의 창이 아닌 여러 화면들을 전환하며 사용합니다. React Navigation을 이용해서 화면 탐색을 구현할 수 있다. React Navigation은 Android 및 iOS에서 공통 스택 탐색 및 탭 탐색 패턴을 간단히 제공합니다.
React Native 프로젝트에 필요한 패키지를 설치해야한다.
npm install @react-navigation/native @react-navigation/stack
React Native 0.60 이상은 아래 패키지를 추가로 설치할 필요가 없다라고 적혀있던데 설치 받아야하네…
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
제대로 설치가 되었다면 App.js
혹은 index.js
를 다음과 같이 변경해보세요!
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
화면을 추가해본다면
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen!</Text>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen!</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home" >
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview' }} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
initialRouteName
는 처음 앱이 실행될때 켜질 화면을 지정한다.
options={{ title: 'Overview' }}
이런식으로 화면에 옵션을 줄 수 있다.
화면으로 속성값 전달
화면으로 속성값을 전달하는 방법은 2가지가 있다는데
- React Context를 이용하는 방법 (권장) (아래에 매개 변수 전달에 나온다.)
- 아래 코드처럼 속성 코드를 넣어주는 방법
<Stack.Screen name="Home">
{props => <HomeScreen {...props} extraData={someData} />}
</Stack.Screen>
참고 : 기본적으로 React Navigation은 불필요한 렌더링을 방지하기 위해 화면 구성 요소에 최적화를 적용합니다. 렌더 콜백을 사용하면 해당 최적화가 제거됩니다. 따라서 렌더 콜백을 사용하는 경우 성능 문제를 피하기 위해 React.memo또는 React.PureComponent화면 구성 요소를 사용하도록해야합니다.
화면 이동
HomeScreen를 다음과 같이 바꾸면 Home -> Details으로 이동하는 버튼이 생깁니다.
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
navigation.navigate('Details')
를 이용하면 화면을 전환할 수 있습니다.
navigate
말고도 다른 것을 알고 싶다면 요기에 자세하게 나와았습니다.
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
<Button
title="Go back to first screen in stack"
onPress={() => navigation.popToTop()}
/>
</View>
);
}
navigation.push
을 하게되면 navigation.navigate
와는 다르게 자기 자신에서 자기 자신을 호출 할 수 있다.
navigation.goBack()
을 이용하면 뒤로가기를 할 수 있습니다.
navigation.popToTop()
는 스택이 여러개 쌓여도 가장 위로 점프한다.
요약이라네요
- React Native에는 웹 브라우저처럼 탐색을위한 API가 내장되어 있지 않습니다.
React Navigation
은 iOS 및 Android 제스처 및 애니메이션과 함께 화면 간 전환을 위해이를 제공합니다. Stack.Navigator
구성에 대한 추가 소품을 사용하여 경로 구성을 하위 구성 요소로 사용하여 콘텐츠를 렌더링하는 구성 요소입니다.- 각
Stack.Screen
구성 요소는name
경로 이름을 나타내는component
소품 과 경로 에 렌더링 할 구성 요소를 지정하는 소품을 가져옵니다. 이것들은 2 가지 필수 소품입니다. - 스택의 초기 경로를 지정하려면
initialRouteName
네비게이터 용 소품으로 제공하십시오. - 화면에 특정 옵션을 지정하려면, 우리는 전달할 수 options에 소품을 Stack.Screen, 그리고 일반적인 옵션, 우리는 전달할 수 screenOptions에
Stack.Navigator
- navigation.navigate(‘RouteName’) 스택 경로에 스택 경로 탐색기가 없으면 새 경로를 푸시합니다. 그렇지 않으면 해당 화면으로 이동합니다.
- 우리는 navigation.push(‘RouteName’)우리가 원하는만큼 전화를 걸 수 있으며 계속해서 노선을 추진할 것입니다.
- 헤더 표시 줄에 자동으로 뒤로 버튼이 표시되지만을 호출하여 프로그래밍 방식으로 돌아갈 수 있습니다 navigation.goBack(). Android에서는 하드웨어 뒤로 버튼이 예상대로 작동합니다.
- navigation.popToTop(). 을 사용하여 스택의 기존 화면으로 돌아가고을 사용하여 스택 navigation.navigate(‘RouteName’)의 첫 번째 화면으로 돌아갈 수 있습니다
- navigation소품 모든 화면 구성 요소 (경로 구성의 화면과 같이 정의 경로로 탐색 반응에 의해 렌더링 구성 요소)을 사용할 수 있습니다.
매개 변수 전달
두가지 방법이 있다
navigation.navigate
함수의 두 번째 매개 변수로 객체에 매개 변수를 넣어 경로에 매개 변수를 전달navigation.navigate('RouteName', { /* params go here */ })
- 화면 구성 요소의 매개 변수를 넣기. (비추천)
첫번째 방법을 이용하면 다음과 같다.
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId } = route.params;
const { otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() =>
navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})
}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
기본값 지정
기본 값도 지정할 수 있는데 Screen 설정하는 곳에 initialParams
속성을 사용하면 된다.
<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>
이전 화면으로 매개 변수 전달
이전 화면에도 매개변수를 전달해줄 수 있다.
화면을 오픈할때 쓴 navigate
함수나 goBack
함수를 이용하여 이전 화면에 메개 변수를 줄 수 있다.
navigation.navigate('Home', { post: postText });
이렇게
navigate
를 이용한 예제 코드이다.
function HomeScreen({ navigation, route }) {
React.useEffect(() => {
if (route.params?.post) {
// Post updated, do something with `route.params.post`
// For example, send the post to the server
}
}, [route.params?.post]);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Create post"
onPress={() => navigation.navigate('CreatePost')}
/>
<Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
</View>
);
}
function CreatePostScreen({ navigation, route }) {
const [postText, setPostText] = React.useState('');
return (
<>
<TextInput
multiline
placeholder="What's on your mind?"
style={{ height: 200, padding: 10, backgroundColor: 'white' }}
value={postText}
onChangeText={setPostText}
/>
<Button
title="Done"
onPress={() => {
// Pass params back to home screen
navigation.navigate('Home', { post: postText });
}}
/>
</>
);
요약이라고 하네요
navigate
그리고push
당신은 당신이로 이동하는 경로에 매개 변수를 전달할 수 있도록 선택적인 두 번째 인수에 동의합니다. 예를 들면 다음과 같습니다navigation.navigate('RouteName', {paramName: 'value'})..
- 당신은
route.params
화면 내부를 통해 매개 변수를 읽을 수 있습니다 - 당신은 화면의 매개 변수를 업데이트 할 수 있습니다
navigation.setParams
- 초기 매개 변수는
initialParams
소품을 통해 전달 될 수 있습니다 .Screen
이 페이지 편집
헤더 바
타이틀을 변경하고 싶다면 option으로 title
을 주면 된다.
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'My home' }}
/>
</Stack.Navigator>
그 외에도 이미지랑 색갈 등등을 지정해줄 수 있다.
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: 'My home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
/>
</Stack.Navigator>
구성요소에 대한 공통을 넣을 수가 있다. Stack.Navigator.screenOptions
선언에 넣으면 모든 화면에 공통으로 적용된다.
function StackScreen() {
return (
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'My home' }}
/>
</Stack.Navigator>
);
}
헤더 버튼 정의
기본으로 제공하는 헤더 버튼을 커스텀 마이징 할 수 있다. 필요할때 가져다 쓰는걸로.. 여기
구성요소 업데이트
구성 요소 자체를 업데이트 해야하는 경우 navigation.setOptions
을 사용하면 된다.
<Button
title="Update the title"
onPress={() => navigation.setOptions({ title: 'Updated!' })}
/>
중첩 네비게이터
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Messages" component={Messages} />
</Tab.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
);
}
주의사항
- 각 탐색기는 자체 탐색 기록을 유지한다. 예를 들어, 중첩 스택 네비게이터 내부에서 뒤로 단추를 누르면 상위로 다른 네비게이터가 있어도 중첩 스택 내부의 이전 화면으로 돌아갑니다.
- 현재 네비게이터에서 처리할 수 없는 경우 버블 업
navigation.goBack()
를 호출당시 중첩 내비게이터의 첫번째 화면인 경우 상위 네이게이터로 이동한다. - 부모 네비게이터의 이벤트를 받지 않는다.
중첩 된 네비게이터에서 화면 탐색
다음같은 화면 구성이 있을 때 탐색하는 방법 알아보면
function Root() {
return (
<Stack.Navigator>
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Root" component={Root} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Home
에서 Root
로 스택을 이용할 때
navigation.navigate('Root');
Home
에서 Root
에 Settings
로 이용할 때
navigation.navigate('Root', { screen: 'Settings' });
매개 변수를 전달할때
navigation.navigate('Root', {
screen: 'Settings',
params: { user: 'jane' },
});
네비게이터에 정의된 초기 경로 무시
navigation.navigate('Root', {
screen: 'Settings',
initial: false,
});
중첩시 모범 사례
중첩 네베게이터는 최소안으로 적용하는게 좋다. 중첩을 사용하게되면 화면 전환이나 중첩된 화면을 탐색 할 때 코드를 작성하기 힘들고 하위 계층을 사용하다보면 메모리 및 성능 문제를 일으킬 수 있다.
네비게이션 생명주기
몰라ㅠ
네비게이션 문제가 발생했을떄
- 여기을 참고 하면 된다.
Networking
REST API 같은 통신하는 방법 FATCH API
기본 사용방법
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue'
})
});
처리 방법
- 비동기 처리 (기본)
const getMoviesFromApi = () => { return fetch('https://reactnative.dev/movies.json') .then((response) => response.json()) .then((json) => { return json.movies; }) .catch((error) => { console.error(error); }); };
- 동기 처리 방법
const getMoviesFromApiAsync = async () => { try { let response = await fetch( 'https://reactnative.dev/movies.json' ); let json = await response.json(); return json.movies; } catch (error) { console.error(error); } };
예제
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
export default App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://reactnative.dev/movies.json')
.then((response) => response.json())
.then((json) => setData(json.movies))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.title}, {item.releaseYear}</Text>
)}
/>
)}
</View>
);
};
fetch 쿠기 기반 인증의 문제
통신을 직접 작성하기에 문제가 될지는 모르겠지만 나중에 외부 API를 사용할 때 문제가 되었다면 여기