React Navigation 설치

npx expo install react-native-screens react-native-safe-area-context

npm으로 설치할 수도 있으나 npx로 설치해야, react-navigation 을 expo에 딱 맞는 버전으로 설치해준다.

npm으로는 3.3으로 설치됨 npx로 설치할 때는 4.3

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';

export default function App() {
	return (
		<NavigationContainer>{/* Rest of your app code */}</NavigationContainer>
	);
}

Stack Navigator 사용하기

종류가 두가지있음

  • Stack (js로 만듬)
  • Native Stack (native 에 맞게 제작)

안드로이드 ios 에 모두 맞게 만들어진 것은 Native Stack 네비게이터임

스크린을 쌓는 것이 stack의 원리 이다. 뒤로 돌아갈 때는 pop 되는 것임.

import SignInScreen from '../screens/SigninScreen';

const {
	createNativeStackNavigator,
} = require('@react-navigation/native-stack');

const Stack = createNativeStackNavigator;

const AuthStack = () => {
	return (
		<Stack.Navigator>
			<Stack.Screen
				name={'SignIn'}
				component={SignInScreen}
			></Stack.Screen>
		</Stack.Navigator>
	);
};

export default AuthStack;

위와 같이 AuthStack.js 파일을 만들어서 네비게이션 설정 해준다.

그러면 App.js에서

const App = () => {
	return (
		<NavigationContainer>
			<StatusBar style="dark" />
			<AuthStack />
		</NavigationContainer>
	);
};

위와 같이 해주면 Navigation을 써서 화면 전환을 해줄 수 있다.

navigation 함수를 이용해서 route 전환을 해줄 수 있다.

const SignInScreen = ({ navigation, route }) => {
    ...
    navigation.push('List');

위와 같이 기본 함수컴포넌트에 전달할 때, navigation, route 정보를 주고 받으며

navigation.push 함수를 사용하여 넣어준다.

  • push : 화면을 쌓으면서 이동
  • navigate : route로 이동하는 것임.

route.params 안에서 변수를 전달할 수 있다.

option 설정

방법은 3가지

  • screenOptions
  • options
  • navigation.setOptions

우선순위는 setOptions가 가장 높음 덮어쓰기가 됨.


<Stack.Navigator
            initialRouteName="List"
            screenOptions=\{\{
                contentStyle: {
                    backgroundColor: '#fff',
                },
            \}\}
        >

위와 같이 해주면 모든 color가 흰색이 됨

<Stack.Navigator
	initialRouteName="List"
	screenOptions=\{\{
		contentStyle: {
			backgroundColor: '#fff',
		},
	\}\}
>
	<Stack.Screen
		name={'List'}
		component={ListScreen}
		options={{
			contentStyle: {
				backgroundColor: 'lavender',
				borderRadius: 30,
			},
		}}
	/>
	<Stack.Screen name={'SignIn'} component={SignInScreen} />
</Stack.Navigator>

덮어써져서 option의 속성을 가져가는 것을 볼 수 있음.

useEffect(() => {
	navigation.setOptions({
		contentStyle: {
			backgroundColor: 'lightgray',
		},
	});
});

위와 같이 해주면 회색으로 칠해짐.

헤더 타이틀 변경

<Stack.Screen
	name={'SignIn'}
	component={SignInScreen}
	options={{
		title: 'ToDo List',
	}}
/>

위와 같이title을 설정해줄 수 있음.

title 중앙정렬

<Stack.Navigator
            initialRouteName="List"
            screenOptions={{
                contentStyle: {
                    backgroundColor: WHITE,
                },
                headerTitleAlign: 'center',
            }}
        >

움직일때마다 바뀌게끔 만들어줌

headerTitle: (props) => {
                        return (
                            <Pressable>
                                <Text style={{ color: props.tintColor }}> {props.children}</Text>
                            </Pressable>
                        );
                    },

navigation 에서 설정하는 props를 가져가서 받을 수 있다.

헤더 왼쪽 버튼

 headerLeft: ({ canGoBack, tintColor }) => {
                    const navigation = useNavigation();

                    if (!canGoBack) {
                        return null;
                    } else {
                        return (
                            <Pressable onPress={navigation.goBack}>
                                <MaterialCommunityIcons name="chevron-left" size={30} color={tintColor} />
                            </Pressable>
                        );
                    }
                },

위와 같이 커스터마이징 할 수 있다.

여기서 유념해야하는 것은 navigation은 context가 다른 경우 useNavigation으로 가져올 수 있다는 점!

이를 함수로 만들어서 아래와 같이 정리하였음. HeaderLeftButton.js

import { Button, StyleSheet, View, Text } from 'react-native';

const ListScreen = ({ navigation, route }) => {
	console.log(route.params);
	return (
		<View style={styles.container}>
			<Text>ListScreen</Text>
			<Button
				title="navigate"
				onPress={() => navigation.push('SignIn', { ts: Date.now() })}
			></Button>
		</View>
	);
};

const styles = StyleSheet.create({
	container: {
		flex: 1,
		justifyContent: 'center',
		alignItems: 'center',
	},
});

export default ListScreen;
  • hitslop 이라는 option을 주면 클릭의 오차범위를 확대할 수 있음.
<Pressable onPress={navigation.goBack} hitSlop={10}>

헤더의 오른쪽 버튼 추가

headerRight 에 옵션 주면 됨

  • 안전한 영역에만 자식 컴포넌트가 렌더링 되도록 SafeAreaView 컴포넌트를 사용하면 된다.