일반적으로 모바일 애플리케이션은 하나의 화면이 아닌, 다양한 화면이 상황에 맞게 전환되면서 나타남.
=> 내비게이션(navigation)은 모바일 애플리케이션에서 가장 중요한 기능 중 하나임!!
=> 리액트 네이티브에서는 내비게이션을 지원하지 않는다. 외부 라이브러리를 이용해야 한다.
1. 🤍리액트 내비게이션
- 리액트 네이티브 애플리케이션의 내비게이션을 쉽고 간단하게 관리할 수 있도록 도와줌
- 지원하는 내비게이션 종류 : 스택(stack) 내비게이션, 탭(tab) 내비게이션, 드로어(drawer) 내비게이션
- 구조 : NavigationContainer, Navigator, Screen 컴포넌트
- Screen 컴포넌트 : 화면으로 사용되는 컴포넌트로, name과 component 속성을 지정해야함. name은 화면 이름, component에는 화면으로 사용될 컴포넌트를 전달함.(화면으로 사용되는 컴포넌트에는 항상 navigaion과 route가 props로 전달됨.)
- Navigator 컴포넌트 : 화면을 관리하는 중간 관리자 역할. 여러 개의 Screen 컴포넌트를 자식 컴포넌트로 갖고 있음.
- NavigationContainer : 내비게이션의 계층 구조, 상태를 관리하는 컨테이너 역할. 모든 구성 요소를 감싼 최상위 컴포넌트.

2. 🤍리액트 내비게이션 실습
프로젝트 생성
<javascript />
expo init react-native-navigaion //프로젝트 생성 npm install styled-components //스타일드 컴포넌트 라이브러리 설치
리액트 내비게이션 라이브러리 설치
<javascript />
//라이브러리 설치 npm install --save @react-navigaion/native //종속성 설치 expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
전체 디렉토리 구조

2.1. 1. 스택 내비게이션(Stack Navigaion)
- 가장 많이 사용되는 내비게이션
- 현재 화면 위에 다른 화면을 쌓으며 화면을 이동하는 것이 특징임. ex) 채팅방 입장, 여러 목록 중 특정 항목의 상세 화면으로 이동
<javascript />
npm install @react-navigation/stack //스택 라이브러리 설치
첫 화면 Home 컴포넌트, 다음 화면인 List 화면으로 이동하기 위한 버튼으로 구성되어 있음.
<javascript />
const Home = () => { return( <Container> <StyledText>Home</StyledText> <Button title="go to the list screen" /> </Container> ); };

목록 화면으로 사용할 List 컴포넌트
<javascript />
const items = [ {_id: 1, name: 'React Native'}, {_id: 2, name: 'React Navigation'}, {_id: 3, name: 'JavaScript'}, ]; const List = () => { const _onPress = item => {}; return( <Container> <StyledText>List</StyledText> {items.map(item=>( <Button key={item._id} title={item.name} onPress={()=>_onPress(item)} /> ))} </Container> ); }; export default List;
Item 컴포넌트에 임시 데이터를 생성 후,
상세 정보를 보여주는 Stack 컴포넌트 작성
=> Navigator 컴포넌트 안에 Screen 컴포넌트를 자식 컴포넌트로 작성, 앞에서 만든 컴포넌트를 Screen 컴포넌트의 component로 지정함. name에는 화면의 이름을 작성하며, Screen 컴포넌트의 name은 반드시 서로 다른 값을 가져야함!
<javascript />
const Stack = createStackNavigator(); const StackNavigation = () => { return ( <Stack.Navigator> <Stack.Screen name="Home" component={Home} /> <Stack.Screen name="List" component={List} /> <Stack.Screen name="Item" component={Item} /> </Stack.Navigator> ); }; export default StackNavigation;
스택 내비게이션에서 첫 번째 화면으로 나오는 화면을 따로 지정하고 싶을 때에는 initialRouteName 속성을 사용함.
<javascript />
<Stack.Navigator initialRouteName="List"> ... </Stack.Navigator>
📱실행 화면

2.2. 2-1. 화면 이동
- Screen 컴포넌트의 component로 지정된 컴포넌트는 화면으로 이용되고, navigation이 props로 전달됨.
- navigation의 다양한 기능 중 navigate 함수는 원하는 화면으로 이동하는 데에 사용됨.
- 전달되는 화면 이름은 Screen 컴포넌트의 name 값 중 하나를 입력해야함!
<javascript />
/* Home 화면에서 props로 전달되는 navigation을 사용해서 버튼 클릭 시 List 화면으로 이동하도록 */ const Home = ({navigation}) => { return( <Container> <StyledText>Home</StyledText> <Button title="go to the list screen" onPress={()=>navigation.navigate('List')} /> </Container> ); };

📱실행 화면

2.3. 2-2. 상세 화면 이동
- 상세 화면은 어떤 내용을 렌더링해야 하는지 전달받아야함.
- navigate 함수를 이용할 때 두 번째 파라미터에 객체를 전달해서 이동하는 화면에 필요한 정보를 함께 전달하는 기능이 있음.
Item 화면으로 이동하면서 항목의 id와 name을 전달하도록 작성. 전달된 내용은 컴포넌트의 props로 전달되는 route의 params를 통해 확인 가능함.
<javascript />
const List = ({navigation}) => { const _onPress = item => { //List 화면에서 목록 클릭 시 해당 항목의 정보와 함께 Item 화면으로 이동 navigation.navigate('Detail',{id: item._id, name: item.name}); };

Item 화면에서 전달되는 params를 이용해 화면에 항목의 id와 name 출력하기

📱실행 화면

2.4. 3. 스타일 수정하기
헤더 스타일으 수정하는 속성은 헤더의 배경색을 수정하는 headerStyle, 헤더의 타이틀 컴포넌트의 스타일을 수정하는 headerTitleStyle이 있다.
<javascript />
<Stack.Navigator initialRouteName="Home" screenOptions={{cardStyle: {backgroundColor: '#ffffff'}, headerStyle: { height: 110, backgroundColor: '#95a5a6', borderBottomWidth: 5, borderBottomColor: '#34495e', }, headerTitleStyle: {color: '#ffffff', fontSize: 24}, headerTitleAlign: 'center', headerTitle: ({ style }) => ( <MaterialCommunityIcons name="react" style={style} /> ), }} >
📱실행 화면

- 헤더의 타이틀을 변경하기 위해 문자열을 지정했던 headerTitle 속성에 컴포넌트를 반환하는 함수 지정 시, 타이틀 컴포넌트를 반환하는 컴포넌트로 변경할 수 있음.
- headerTitle에 함수가 설정되면 해당 함수의 파라미터로 style, tintColor 등이 포함된 객체가 전달됨. => 그 중 style은 headerTitleStyle에 설정된 값, tintColor는 headerTintColor에 지정된 값이 전달된다.
vector-icons에서 제공하는 컴포넌트를 이용하여 리액트 로고가 랜더링되도록 작성.

📱실행 화면

headerLeft, headerRight에 컴포넌트를 변환함수를 지정하여 헤더 양 끝에 원하는 컴포넌트를 렌더링 해보기
- useLayoutEffect Hook : useEffect Hook과 사용법이 동일하지만, 컴포넌트 업데이트된 직후 화면이 렌더링되기 전에 실행된다는 차이점이 있음. => 화면 렌더링하기 전에 변경할 부분이 있거나 수치 등을 측정해야 하는 상황에서 많이 사용됨.
- headerLeft의 onPress는 뒤로 가기 버튼 기능이 전달됨.
- headerRight 함수의 파라미터는 tintColor만 전달되므로 onPress에 원하는 행동을 정의해야함.
- popToTop 함수는 현재 쌓여있는 모든 화면을 내보내고 첫 화면으로 돌아가는 기능.
<javascript />
const Item = ({navigation, route}) => { useLayoutEffect(()=>{ navigation.setOptions({ headerBackTitleVisible: false, headerTintColor: '#ffffff', headerLeft: ({onPress, tintColor})=>{ return( <MaterialCommunityIcons name="keyboard-backspace" size={30} color={tintColor} onPress={onPress} /> ); }, headerRight: ({tintColor})=>( <MaterialCommunityIcons name="home-variant" size={30} style={{marginRight: 11}} color={tintColor} onPress={()=>navigation.popToTop()} /> ), }); }, []);
📱실행 화면

2.5. 4. 탭 내비게이션(Tab Navigation)
탭 내비게이션은 보통 화면 위 or 아래에 위치하며, 탭 버튼을 누르면 연결된 화면으로 이동하는 방식으로 동작함.
<javascript />
npm install @react-navigation/bottom-tabs //탭 내비게이션 라이브러리 설치

3개의 버튼과 해당 버튼과 해당 버튼에 연결된 화면으로 구성된 탭 내비게이션을 만들 것이며, 먼저 화면으로 사용할 TabScreen 컴포넌트를 작성.
<javascript />
export const Mail = () => { return( <Container> <StyledText>Mail</StyledText> </Container> ); }; export const Meet = () => { return( <Container> <StyledText>Meet</StyledText> </Container> ); }; export const Settings = () => { return( <Container> <StyledText>Settings</StyledText> </Container> ); };
위에서 생성된 컴포넌트를 이용해 탭 내비게이션 구성
<javascript />
const Tab = createBottomTabNavigator(); const TabNavigation = ()=>{ return( <Tab.Navigator> <Tab.Screen name="Mail" component={Mail} /> <Tab.Screen name="Meet" component={Meet} /> <Tab.Screen name="Settings" component={Settings} /> </Tab.Navigator> ); }; export default TabNavigation;
📱실행 화면


2.6. 5. 버튼 아이콘 설정하기
- 화면을 구성하는 Screen마다 tabBarIcon에 MaterialCommunityIcons 컴포넌트를 반환하는 함수 지정
- 반환 컴포넌트의 색과 크기는 TabBarIcon에 지정된 함수의 파라미터로 전달되는 color와 size를 이용해 설정
<javascript />
import {MaterialCommunityIcons} from "@expo/vector-icons"; const TabIcon = ({name, size, color})=>{ return <MaterialCommunityIcons name={name} size={size} color={color}/>; }; const TabNavigation = () => { return( <Tab.Navigator ... > <Tab.Screen name="Mail" component={Mail} options={{ tabBarIcon: props => TabIcon({...props, name: 'email' }), }} /> <Tab.Screen name="Meet" component={Meet} options={{ tabBarIcon: props => TabIcon({ ...props, name: 'video', }), }} /> <Tab.Screen name="Settings" component={Settings} options={{ tabBarIcon: props => TabIcon({ ...props, name: 'settings', }), }} /> </Tab.Navigator> ); };
💡만약 Screen 컴포넌트마다 탭 버튼 아이콘을 지정하지 않고 한 곳에서 모든 버튼의 아이콘을 관리하고 싶을 경우 Navigator 컴포넌트의 screenOptions 속성을 사용해서 관리할 수 있다.
<javascript />
//컴포넌트마다 아이콘을 지정하지 않고 한 곳에서 모든 버튼의 아이콘을 관리 // screenOptions={({route})=>({ // tabBarIcon: props => { // let name = ''; // if (route.name === 'Mail') name = 'email'; // else if (route.name === 'Meet') name = 'video'; // else name = 'settings'; // return TabIcon({...props, name}); // }, // })}
📱실행 화면

+기타 다른 스타일 수정 사항들, 주석 설명
<javascript />
<Tab.Navigator /* 탭 버튼 순서는 변경하지 않고, 렌더링되는 첫 번째 화면을 변경하고 싶은 경우 : initialRouteName 속성 이용 */ initialRouteName="Settings" tabBarOptions={{ //비활성화된 상태 색 설정 //activeTintColor: '#ffffff', inactiveTintColor: '#0B92E9', //탭 바 스타일 변경 style: { backgroundColor: '#54b7f9', borderTopColor: '#ffffff', borderTopWidth: 2, }, //버튼 아이콘의 아래가 아닌 아이콘 옆에 렌더링 labelPosition: 'beside-icon', //아이콘만 나타나도록 showLabel: false, }} >
📱실행 화면

tabBarOptions의 style 속성이 먹히지 않는다ㅠㅠㅠ아직 이유 못찾음...
'💻 my code archive > ✨React-Native' 카테고리의 다른 글
[리액트 네이티브] 채팅 애플리케이션 만들기 2. 내비게이션, 로그아웃, 프로필 화면 (0) | 2022.07.22 |
---|---|
[리액트 네이티브] 채팅 애플리케이션 만들기 1.파이어베이스 세팅, 로그인, 회원가입 (0) | 2022.07.21 |
[리액트 네이티브] ContextAPI, Consumer, Provider 실습 (0) | 2022.07.14 |
[리액트 네이티브] Hooks, useEffect, useRef, useMemo, 커스텀 Hooks 만들기 (0) | 2022.07.13 |
[리액트 네이티브] 할 일 관리 Todo List 애플리케이션 만들기 (0) | 2022.07.12 |