react native 에서 사용할 수 있는 네비게이션 라이브러리는 두 가지가 있다
react-navigation : 리액트 네이티브 커뮤니티에서 관리하는 사용률이 가장 높은 라이브러리, 공식 문서에서도 소개하고 있다
reat-native-navigation: 홈페이지 제작 서비스 Wix 에서 관리한다 이미 만들어진 네이티브 앱에 사용하는 편이 좋다 조금 더 네이티브 스러운 사용 경험
App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
const App() {
return <NavigationContainer>{/* 내비 설정 */}</NavigationContainer>
}
export default App
NavigationContainer 컴포넌트로 사용할 앱 전체를 감싸주어야 한다
웹 브라우저에는 History 기능은 Stack 자료구조를 사용해 구현되어 있다
React Navigation 을 네이티브로 사용할 때는 사용성을 제공하기 위해
Native Stack Navigator 를 사용한다
Native Stack Navigator 는 가장 흔히 사용되고
안드로이드에서는 Fragment 를 iOS 에서는 UINavigationController 를
사용해 일반 네이티브 앱과 정확히 동일한 방식으로 화면을 관리합니다.
네이티브 스택 내비게이터를 사용하기 위해서는 라이브러리를 추가로 설치해주어야 한다
npm install @react-navigation/native-stack
App.js
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import HomeScreen from './screens/HomeScreen';
import DetailScreen from './screens/DetailScreen';
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Detail" component={DetailScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
createNativeStackNavigator 함수를 사용하면 Stack 객체가 생성된다
객체 안의 Navigator 와 Screen 컴포넌트를 사용해 화면을 설정할 수 있다
이 컴포넌트의 name 은 화면의 이름을 설정하는 Props
화면 이름은 공식 문서에서 대문자로 시작하는 것을 권장한다
Navigator 로 Screen 을 감싸 사용
navigation.navigate('Detail')
를 사용해 화면 이동
push 함수를 사용해도 화면 전환할 수 있다
push 함수를 사용하면 같은 화면도 계속 네비게이션 스택에 쌓인다
navigate 는 push 와 달리 새로 이동할 화면이 현재 화면과 같으면 새로운 화면을 쌓지 않고 파라미터만 변경한다
뒤로가기를 할 때는 pop, 가장 첫 번째 화면으로 가려면 popToTop 메서드 사용
react-navigation 에서는 타이틀 영역을 header 라고 부른다
App.js
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: '홈',
}}
/>
<Stack.Screen name="Detail" component={DetailScreen} />
</Stack.Navigator>
HomeScreen.js
import React, {useEffect} from 'react';
import {View, Button} from 'react-native';
function HomeScreen({navigation}) {
useEffect(() => {
navigation.setOptions({title: '홈'});
}, [navigation]);
return (...);
}
export default HomeScreen;
detail 페이지에는 라우터 파라미터로 받아온 route 의 id 를 값을 포함하도록할 때
Screen 에서 Props 설정 시 options 에는 객체를 반환하는 함수를 넣어준다
함수는 route 와 navigation 을 파라미터로 받아올 수 있다
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: '홈',
}}
/>
<Stack.Screen
name="Detail"
component={DetailScreen}
options={({route}) => ({
title: `상세 정보 - ${route.params.id}`,
})}
/>
</Stack.Navigator>
헤더 스타일 변경 시 Screen 컴포넌트의 headerStyle, headerTintColor, headerTitleStyle
등의 속성을 사용할 수 있다
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
title: '홈',
// Header 블록에 대한 스타일
headerStyle: {
backgroundColor: '#29b6f6',
},
// Header의 텍스트, 버튼들 색상
headerTintColor: '#ffffff',
// 타이틀 텍스트의 스타일
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 20,
},
}}
/>
opstions 에 headerLeft, headerTitle, headerRight 를 갖는 객체를 반환한다
각 키들은 값으로 컴포넌트를 리턴하는 함수를 가진다
<Stack.Screen
name="Detail"
component={DetailScreen}
options={{
headerLeft: ({onPress}) => (
<TouchableOpacity onPress={onPress}>
<Text>Left</Text>
</TouchableOpacity>
),
headerTitle: ({children}) => (
<View>
<Text>{children}</Text>
</View>
),
headerRight: () => (
<View>
<Text>Right</Text>
</View>
),
}}
/>
안드로이드는 좌측에 화살표 아이콘이 나타난다는데
headerBackVisible 옵션을 false 로 지정하면 된다
<Stack.Screen
name="Detail"
component={DetailScreen}
options={{
headerBackVisible: false,
headerLeft: ({onPress}) => (
Navigator 의 screenOptions 에 headerShown: false 를 주면 된다
screenOptions={{
headerShown: false,
}}
드로어 내비게이터는 좌/우측에 사이드 바를 만들 때 사용
사이드 바를 모바일에서는 드로어라고 부른다
drawerContent 에 SafeAreaView 를 꼭 사용한다
그렇지 않으면 드로어 상단 영역이 StatusBar 영역과 겹친다
하단 탭 네비게이터는 전체 영역에 대해 swipe 를 막는 옵션이 없던 것 같은데
상단 탭 내비게이터의 옵션을 bottom 으로 주어 사용하는 편이 좋지 않을까 싶기도..
아마 내가 사용해봤던게 머터리얼 하단 탭이라 그럴지도 모르겠다
tabBarKeyboardHidesTabBar 옵션을 통해 키보드 생성 시 하단 탭을 가린다는데
어떨지 모르겠다 사용해보고 너무 차이나게 좋으면 하단 탭으로 변경을 고려해보는 편도..
• Stack.Navigator
- Main (Tab.Navigator)
• Home
• Search
• Notification
• Message
- Detail
stack 내비게이터 안에 탭 네비게이터 를 사용할 수 있다
머터리얼 하단 탭 네비게이터는 하단에만 나타나고
활성화된 탭에 따라 전체 탭의 배경색을 변경할 수 있다
탭이 활성화되면 해당 탭이 살짝 올라온다
상단 탭은 상단, 하단 모두 가능
네비게이션에 관련된 Hooks 도 있다
navigation 이나 route 객체를 사용중이 아닌 컴포넌트에서 사용하도록
하는 방법은 3가지가 있다
function OpenDetailButton({onPress}) {
return <Button title="Detail 1 열기" onPress={onPress} />;
}
function HomeScreen({navigation}) {
return (
<View>
<Text>Home</Text>
<OpenDetailButton onPress={() => navigation.push('Detail', {id: 1})} />
</View>
);
}
function OpenDetailButton({navigation}) {
return (
<Button
title="Detail 1 열기"
onPress={() => navigation.push('Detail', {id: 1})}
/>
);
}
function HomeScreen({navigation}) {
return (
<View>
<Text>Home</Text>
<OpenDetailButton navigation={navigation} />
</View>
);
}
useNavigation 훅을 호출하면 navigation 객체를 반환한다
const navigation = useNavigation();
useRoute 훅을 호출하면 route 객체를 반환한다
const route = useRoute();
useFocusEffect는 꼭 useCallback과 같이 사용한다
useCallback을 사용하지 않으면 컴포넌트가 리렌더링될 때마다 useFocusEffect에 등록한함수가 호출된다
useCallback은 컴포넌트 내부에서 함수를 만들 때
매번 새로 만든 함수를 사용하지 않고 이전에 만든 함수를 다시 사용한다
함수 내부의 로직에서 의존하는 값이 있다면 의존하는 값이 바뀌었을 때 함수를 교체한다