일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- REACT
- Ai
- Programmers
- 프로그래머스
- 알고리즘기초주차
- 항해99
- 스파르타코딩클럽
- rn
- typeScript
- 팀워크최고
- 7기
- TS
- NotionAI
- Expo
- 달리기반
- 맥린이
- 사전준비
- 프론트엔드
- 알pdf #파일탐색기미리보기안될때
- 챗GPT
- 코린이
- 멍친구
- 웹개발종합반
- 리액트
- 필수강의
- TDD
- D반8조
- ChatGPT
- ReactNative
- 실전프로젝트
- Today
- Total
FrontEnd :-)
[RN] study 6week / 리액트 내비게이션 ② 본문
React Navtive 스터디 6week
도서: [리액트 네이티브를 다루는 기술 / 김민준 / 길벗]
(5장 리액트 내비게이션으로 여러 화면 관리하기 ②)
5.1 설치 및 적용하기
5.2 기본적인 사용법
5.3 다양한 내비게이터
5.4 내비게이션 Hooks
5.5 정리
5.3 다양한 내비게이터
5.3.1 드로어 내비게이터
@react-navigation/drawer : Drawer Navigator 는 좌측 또는 우측에 사이드바를 만들고 싶을 때 사용하는 내비게이터. 사이드바를 모바일 앱에서는 드로어(Drawer)라고 함.
https://reactnavigation.org/docs/drawer-navigator/
yarn add @react-navigation/drawer react-native-gesture-handler react-native-reanimated
cd ios
pod install
cd ../
yarn start
react-native-gesture-handler : 드로어 내비게이터에서 사용자 제스처를 인식하기 위해 내부적으로 사용하는 라이브러리.
react-native-reanimated : 리액트 네이티브에 내장된 애니메이션 효과 기능보다 더욱 개선된 성능으로 애니메이션 효과를 구현해주는 라이브러리.
(※ 이전에 사용한 navigation.push, pop 기능들은 드로어 내비게이터에서 호환되지 않음!)
>Error : react-native-reanimated 설치하면
Add Reanimated's babel plugin to your babel.config.js:
module.exports = {
presets: [
...
],
plugins: [
...
'react-native-reanimated/plugin',
],
};
https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation/#babel-plugin
5.3.1.1 드로어 커스터마이징하기
드로어 타이틀 변경: options 설정
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{title: '홈'}}
/>
드로어 스타일 변경: screenOptions 설정
• drawerActiveTintColor: 활성화된 항목의 텍스트 색상
• drawerActiveBackgroundColor: 활성화된 항목의 배경색
• drawerInactiveTintColor: 비활성화된 항목의 텍스트 색상
• drawerInactiveBackgroudnColor: 비활성화된 항목의 배경색
• drawerItemStyle: 항목의 스타일
• drawerLabelStyle: 항목 내부의 텍스트 스타일
• drawerContentContainerStyle: 항목들을 감싸고 있는 영역의 스타일
• drawerStyle: 전체 드로어를 감싸고 있는 영역의 스타일
<Drawer.Navigator
initialRouteName="Home"
// drawerPosition="left"
backBehavior="history"
screenOptions={{
drawerActiveBackgroundColor: '#f48fb1', //활성화된 항목의 배경색
drawerActiveTintColor: 'white', //활성화된 항목의 텍스트 색상
drawerInactiveBackgroundColor: '#fbe8ef', //비활성화된 항목의 배경색
drawerInactiveTintColor: 'pink', //비활성화된 항목의 텍스트 색상
drawerLabelStyle: {fontWeight: 'bold'}, //항목 내부의 텍스트 스타일
}}>
Drawer 컴포넌트가 나타나는 영역에 아예 다른 UI 보여주고 싶으면? drawerContent Props에 함수 컴포넌트 삽입!
<Drawer.Navigator
//(...)
drawerContent={({navigation}) => (
<SafeAreaView>
<Text>A Custom Drawer</Text>
<Button onPress={() => navigation.closeDrawer()} title="닫기" />
</SafeAreaView>
)}>
5.3.2 하단 탭 내비게이터
Bottom Tab Navigator: 하단에 탭을 보여주는 내비게이터
https://reactnavigation.org/docs/bottom-tab-navigator/
yarn add @react-navigation/bottom-tabs
cd ios
pod install
cd ../
yarn start
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {Text} from 'react-native';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function HomeScreen() {
return <Text>Home</Text>;
}
function SearchScreen() {
return <Text>Search</Text>;
}
function NotificationScreen() {
return <Text>Notification</Text>;
}
function MessageScreen() {
return <Text>Message</Text>;
}
function App() {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="Home">
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Notification" component={NotificationScreen} />
<Tab.Screen name="Message" component={MessageScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
export default App;
아이콘 사용 위해 ios/프로젝트 이름 / info.plist - 최하단, android/app/build.gradle - 최하단에 각각 아이콘 설정 코드 추가해야함(일전에 학습함)
머티리얼아이콘 적용
import Icon from 'react-native-vector-icons/MaterialIcons';
(...)
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
title: '홈',
tabBarIcon: ({color, size}) => (
<Icon name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{
title: '검색',
tabBarIcon: ({color, size}) => (
<Icon name="search" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Notification"
component={NotificationScreen}
options={{
title: '알림',
tabBarIcon: ({color, size}) => (
<Icon name="notifications" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Message"
component={MessageScreen}
options={{
title: '메시지',
tabBarIcon: ({color, size}) => (
<Icon name="message" color={color} size={size} />
),
}}
/>
5.3.2.1 하단 탭 커스터마이징
• tabBarActiveTintColor: 활성화된 항목의 아이콘과 텍스트 색상
• tabBarActiveBackgroundColor: 활성화된 항목의 배경색
<Tab.Navigator
initialRouteName="Home"
screenOptions={{
tabBarActiveTintColor: '#f48fb1',
tabBarShowLabel: false,
}}>
• tabBarInactiveTintColor: 비활성화된 항목의 아이콘과 텍스트 색상
• tabBarInactiveBackgroundColor: 비활성화된 항목의 배경색
• tabBarShowLabel: 항목에서 텍스트의 가시성 설정(기본값: true)
• tabBarShowIcon: 항목에서 아이콘의 가시성 설정(기본값: false)
• tabBarStyle: 하단 탭 스타일
• tabBarLabelStyle: 텍스트 스타일
• tabBarItemStyle: 항목 스타일
• tabBarLabelPosition: 텍스트 위치 'beside-icon'(아이콘 우측) / 'below-icon'(아이콘 하단)
• tabBarAllowFontScaling: 시스템 폰트 크기에 따라 폰트 크기를 키울지 결정(기본값: true)
• tabBarSafeAreaInset: SafeAreaView의 forceInset 덮어쓰는 객체(기본값: {bottom: 'always', top: 'never'})
• tabBarKeyboardHidesTabBar: 키보드가 나타날 때 하단 탭을 가릴지 결정(기본값: false)
5.3.2.2 네이티브 스택 내비게이터와 하단 탭 내비게이터 함께 사용하기
5.3.3 머티리얼 상단 탭 내비게이터
설치
yarn add @react-navigation/material-top-tabs react-native-tab-view react-native-pager-view
설치하고
import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs';
상단 탭으로 대체했더니, (options, tabBarIcon에서 size={24}로 수정도 필요)
// const Tab = createBottomTabNavigator<TabBarList>();
const Tab = createMaterialTopTabNavigator<TabBarList>();
(Render Error) 오류 발생..
@react-native-community/masked-view 설치했더니 됐다.
MaterialTopTabNavigator에 설정할 수 있는 옵션들을 알아봅시다. Tab.Navigator 컴포넌트에는 다음과 같은 Props를 지정해줄 수 있습니다. 다양한 Props가 있는데요. 이 책에서는 주요 Props에 대해서만 알아보겠습니다.
• initialRouteName: 초기 화면의 이름
• screenOptions: 화면의 기본 설정. 하단 탭 내비게이션과 비슷한데, 다음과 같은 추가 옵션이 있습니다.
– swipeEnabled: 화면을 좌우로 스와이프하여 전환할 수 있게 합니다(기본값: true).
– lazy: 특정 탭으로 이동해야만 해당 탭을 렌더링합니다(기본값: true).
– lazyPreloadDistance: lazy 속성이 활성화된 상태에서 몇 칸 뒤 화면을 미리 불러올지 설정합니다(기본값: 0).
– lazyPlaceholder: lazy 속성이 활성화되어 있을 때 아직 보이지 않은 화면에서 보여줄 대체 컴포넌트
– tabBarIndicator: 활성화된 탭을 표시하는 컴포넌트
– tabBarIndicatorStyle: 활성화된 탭을 표시하는 컴포넌트의 스타일
• backBehavior: 뒤로가기할 때의 작동 방식
• tabBarPosition: 탭 바의 위치(top 또는 bottom)
• keyboardDismissMode: 키보드를 숨기는 설정
– auto: 기본값. 화면이 바뀔 때 키보드를 숨깁니다.
– on-drag 화면을 드래그할 때 키보드를 숨깁니다.
– none: 드래그해도 키보드를 숨기지 않습니다.
• sceneContainerStyle: 각 화면에 대한 스타일
• style: 전체 탭 뷰에 대한 스타일
• tabBar: 탭 바를 대체할 수 있는 컴포넌트(공식 매뉴얼 참조)
일부 Props는 생략했습니다. 자세한 내용은 공식 매뉴얼을 참고하세요.
• https://reactnavigation.org/docs/material-top-tab-navigator
그리고 Tab.Screen의 options Props에는 다음과 같은 값들을 설정할 수 있습니다.
• tabBarIcon: 아이콘을 보여주는 함수, { focused: boolean, color: string } 타입의 파라미터를 받아옵니다.
• tabBarLabel: 탭에서 보이는 이름
function MainScreen() {
return (
<Tab.Navigator
initialRouteName="Main"
screenOptions={{
tabBarIndicatorStyle: {
backgroundColor: '#f48fb1', //활성화탭의 밑줄색?
},
tabBarActiveTintColor: '#f48fb1',
}}>
<Tab.Screen
name="Main"
component={HomeScreen}
options={{
tabBarLabel: '홈', //title: '홈'으로 해도 동일한 결과가 나옴
tabBarIcon: ({color}) => <Icon name="home" color={color} size={24} />,
}}
/>
5.3.4 머티리얼 하단 탭 내비게이터
설치
yarn add @react-navigation/material-bottom-tabs react-native-paper
https://reactnavigation.org/docs/material-bottom-tab-navigator/
import 바꿔주고
import {createMaterialBottomTabNavigator} from '@react-navigation/material-bottom-tabs';
const Tab = createMaterialBottomTabNavigator<TabBarList>();
스타일을 바꿀 수 있다.
function MainScreen() {
return (
<Tab.Navigator
initialRouteName="Home"
shifting={true}
activeColor="#fff"
inactiveColor="#3e2465"
barStyle={{backgroundColor: '#694fad'}}>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarLabel: '홈',
tabBarIcon: ({color}) => <Icon name="home" color={color} size={24} />,
tabBarBadge: 'new',
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{
tabBarLabel: '검색',
tabBarIcon: ({color}) => (
<Icon name="search" color={color} size={24} />
),
tabBarColor: 'pink',
}}
/>
- tabBarColor나 타이틀 또는 레벨이 활성화된 탭에서만 보이게 하려면, shifting={true} 설정 필수
- 그런데, tabBarColor가 스크린별로 탭 배경색 바꿔주는 설정인데, 시뮬레이터에서 작동이 안되어서 의문.. 근데 또 expo snack으로는 적용이 된다.
MaterialBottomTabNavigator에 설정할 수 있는 옵션을 알아봅시다. Tab.Navigator 컴포넌트에는 다음과 같은 Props를 지정해줄 수 있습니다.
• initialRouteName: 초기 화면의 이름
• screenOptions: 화면의 기본 설정
• backBehavior: 뒤로가기할 때의 작동 방식
• shifting: 이 값이 true로 지정되어 있으면 탭이 변경될 때마다 배경색을 변경하고, 활성화된 탭만 탭의 이름을 보여줍니다. 탭의 개수가 세 개 이상이면 이 값은 기본적으로 true로 설정됩니다. 만약 이 값을 false로 지정하면 탭마다 배경색을 따로 따로 지정할 수 없고, 모든 탭에 이름이 보이게 됩니다.
• labeled: 탭 아이콘 하단에 탭의 이름을 나타낼지 정하는 값입니다. 이 값을 false로 지정하면 모든 탭에 이름이 나타나지 않습니다(기본값: true).
• activeColor: 활성화된 탭의 아이콘과 텍스트의 색상
• inactiveColor: 비활성화된 탭의 아이콘과 텍스트의 색상
• barStyle: 탭 바에 스타일 적용
그리고 Tab.Screen의 options Props에는 다음과 같은 값을 설정할 수 있습니다.
• tabBarIcon: 아이콘을 보여주는 함수, { focused: boolean, color: string } 타입의 파라미터를 받아옵니다.•
tabBarLabel: 탭에 보이는 이름
• tabBarBadge: 탭 아이콘에 배지를 보여줍니다. 이 값을 true로 설정하면 아이콘 우측 상단에 빨간색 점을 보여줍니다. 이 값을 문자열 또는 숫자로 입력하면 그 내용이 배지에 나타납니다.
5.3.5 머티리얼 하단 탭 내비게이터 헤더 타이틀 동기화하기
//App.tsx
import {
getFocusedRouteNameFromRoute,
NavigationContainer,
RouteProp,
} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import React from 'react';
import TodoMain from './main/TodoMain';
import DetailScreen from './screens/DetailScrren';
import MainScreen from './screens/MainScreen';
type RootStackParamList = {
Main: undefined;
Detail: {id: number};
TodoList: undefined;
};
type MapList = {
Main: undefined;
Search: undefined;
Notification: undefined;
Message: undefined;
};
type HeaderTitleProps = {
route: RouteProp<MapList, keyof MapList>;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
function getHeaderTitle({route}: HeaderTitleProps) {
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Main'; //nullish 병합 연산자, 연산자 좌측에 있는 값이 null 또는 undefined면 우측 값 설정
const nameMap: {[key: string]: string} = {
Main: '홈',
Search: '검색',
Notification: '알림',
Message: '메시지',
};
return nameMap[routeName];
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Main"
component={MainScreen}
options={({route}) => ({
title: getHeaderTitle({route}), // route를 { }로 감싸줘야 정상 작동함. 위에서 설정한 타입때문에?
})}
/>
<Stack.Screen
name="Detail"
component={DetailScreen}
options={({route}) => ({
title: `상세 정보 - ${route?.params?.id}`,
})}
/>
<Stack.Screen name="TodoList" component={TodoMain} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
5.4 내비게이션 Hooks
5.4.1 useNavigation
useNavigation Hook을 사용하면 Screen으로 사용되고 있지 않은 컴포넌트에서도 navigation 객체를 사용할 수 있습니다
//MainScreen.tsx
//useNavigation 훅 사용
function OpenDetailButton() {
const navigation = useNavigation<Props['navigation']>();
return (
<Button
title="Detail 1 열기"
onPress={() => navigation.push('Detail', {id: 1})}
/>
);
}
5.4.2 useRoute
useRoute는 useNavigation과 비슷하게, Screen이 아닌 컴포넌트에서 route 객체를 사용할 수 있게 합니다. DetailScreen 컴포넌트에서 route.params.id를 보여주는 Text를 IDText라는 컴포넌트로 따로 분리시키고, 해당 컴포넌트에서 useRoute Hook 사용해 route 객체를 사용해보세요.
//DetailScreen.tsx
//useRoute 훅 사용
function IDText() {
const route = useRoute<Props['route']>();
return <Text style={styles.text}>id: {route.params.id}</Text>;
}
5.4.3 useFocusEffect
useFocusEffect는 화면에 포커스가 잡혔을 때 특정 작업을 할 수 있게 하는 Hook입니다. 만약 HomeScreen에 DetailScreen을 띄운다면 HomeScreen이 화면에서 사라지는 게 아니라, HomeScreen 위에 DetailScreen을 쌓아서 보여주는 것입니다. 그래서 useEffect Hook을 통해서 컴포넌트가 마운트되거나 언마운트될 때 콘솔에 텍스트를 출력한다면 DetailScreen을 띄울 때 컴포넌트가 언마운트되지 않고, 또 뒤로가기하여 HomeScreen으로 돌아왔을 때 컴포넌트가 마운트되지 않는 것을 확인할 수 있습니다.
만약 다른 화면을 열었다가 돌아왔을 때 특정 작업을 하고 싶다면 useFocusEffect Hook을 사용해야 합니다. 또 현재 화면에서 다른 화면으로 넘어갈 때 특정 작업을 하고 싶다면 useFocusEffect에서 함수를 만들어 반환하면 됩니다.
useFocusEffect는 꼭 useCallback과 같이 사용해야 합니다. 만약 useCallback을 사용하지 않으면 컴포넌트가 리렌더링될 때마다 useFocusEffect에 등록한 함수가 호출될 것입니다.
useCallback은 컴포넌트 내부에서 함수를 만들 때, 새로 만든 함수를 사용하지 않고 이전에 만든 함수를 다시 사용하도록 만들어줍니다.
//MainScreen.tsx
//useFocusEffect 훅 사용
const HomeScreen = ({navigation}: Props) => {
useFocusEffect(
useCallback(() => {
console.log('이 화면을 보고 있어요.');
return () => {
console.log('다른 화면으로 넘어갔어요.');
};
}, []),
);
출판사 홈페이지에서 엄청난 걸 제공하고 있었다.
'React Native' 카테고리의 다른 글
[RN] study 7week / 다이어리 앱 만들기 ①-① (0) | 2023.03.30 |
---|---|
[RN] study 6week / 리액트 내비게이션 ① (0) | 2023.03.17 |
[RN] study 5week / 할일 목록 만들기 ②-③ AsyncStorage (0) | 2023.03.13 |
[RN] study 5week / 할일 목록 만들기 ②-② (0) | 2023.03.13 |
[RN] study 5week / 할일 목록 만들기 ②-① (0) | 2023.03.10 |