1. NavigationContainer와 Navigator , Screen에 관하여
https://reactnavigation.org/docs/getting-started
Screen은 하나의 View 컴포넌트로서 우리가 화면 이동 시 쓸 화면들이다. Screen 하나 하나가 목적지 이다.
Navigator는 Screen의 집합이다. Navigator 속에 Navigate란 함수가 있는데, 이를 이용하면 Navigator 내부에 정의된 Screen들 사이의 이동이 가능하다.
NavigationContainer는 Navigator Tree를 관리하고, Navigatior의 상태들을 알려주는 컴포넌트이다.
해당 컨테이너가 모든 Navigator 구조를 감싸고 있어야 한다.
우리는 주로 출입 파일 (entry file -> 사용자가 처음으로 직면하는 파일 ex) app.js, index.js) 에 모든 Navigation 구조를 쓰는 경우가 많으므로, NavigationContainer로 출입 파일 전체를 감싸는 것이 일반적이다.
2. 코드 리뷰
(1)App.js
a. 기본 내용
Navigator에는 종류가 많지만, 먼저 가장 쉬운 StackNavigator에 대해 배우겠다.
StackNavigator는 Stack 자료형을 이용하여 화면 이동을 구현한 것이다. Stack은 선입후출의 특성을 가진다.
먼저 CreateNativeStackNavigator()라는 함수를 이용해 Stack 네비게이터를 만들고 이를 함수 표현식을 통해 Stack이란 변수에 할당했다. 그렇다면 이제 Stack이 StackNavigator 함수 그 자체이다.
StackNavigator란 함수는 두 가지 멤버를 가진 Object를 반환한다. 하나는 Navigator이고 하나는 Screen이다.
두 멤버 모두 화면 이동에 필요한 환경 설정을 위해 쓰인다.
먼저 Navigator란 요소에 대해 설명하겠다.
Navigator는 무조건 자식요소로 Screen들을 포함하고 있어야 한다.
해당 Navigator 안에 적혀진 Screen 끼리는 화면 이동이 가능하다.
Screen 요소는 가는 노선(route)에 대해 명세한다. name은 우리가 갈 해당 노선(route)의 이름에 대해 명명하는 것이다.
위에서는 name과 컴포넌트에 적힌 값이 같지만,
<Stack.Screen name="A" component={ScreenA} />
만약 이렇게 적혀있으면 ScreenA라는 컴포넌트로 가는 route는 A이다.
navigate 함수를 이용해 ScreenA로 간다면 navigate("A")로 적어줘야 한다.
component 요소에는 이 route로 갈 목적지가 인수로 들어간다.
component 요소에는 컴포넌트 그 자체가 들어간다. 함수(() => {})가 들어가면 안된다.
그러니까 Screen 자체가 적히는 것이다.
헷갈리지 말아야 할 것이 위의 Screen 요소와 Screen이라는 개념 자체는 서로 다른 것이다. Screen 요소는 Screen이란 목적지로 가기 위한 route에 대한 명세이고, Screen은 우리가 갈 목적지, 화면 그 자체 이다.
b. 옵션에 대하여
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Overview' }}
/>
만약 해당 화면으로 이동 시에 추가적인 사전 작업이 필요하다면 options 함수를 이용하여 실현할 수 있다.
위의 예시에서는 title이라는 key 값을 객체로 보내준다.
이는 Screen Header에 적힐 내용을 name 속성이 아니라 title에 적힌 것으로 바꿔주는 것이다.
만약 모든 스크린에 공통적인 사전 작업을 하고 싶다면 부모 요소인 Navigator에 ScreenOptions를 이용하여 일괄적으로 사전작업을 할 수있다.
c. 이동하고 나서
ScreenA는 Navigator 내의 Screen 요소 중 맨 처음에 위치한다. 다른 옵션을 걸어준 게 아니면, 맨 처음에 쓰인 Screen이 첫 화면이 된다. 이제 첫화면인 ScreenA에서 다른 화면으로 이동하는 것을 구현해 보겠다.
버튼 함수를 이용해 화면 이동을 구현했다. 해당 컴포넌트가 클래스형이라서 자세한 로직은 다루지 않겠다.
다만 navigation.navigate("route이름")으로 원하는 곳으로 갈 수 있음을 알자. 만약 해당 화면으로 정보들을 따로 더 보내고 싶다면 {} 객체를 이용해 더 보내면 된다. 해당 코드에서는 ScreenB로 이동시 value라는 key 값도 같이 보냈다.
그럼 스크린B에서 위와 같이 Value 값을 받아 쓸 수 있다.
d. 같은 화면에 다른 정보 가지고 다시 가기
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
위의 예시처럼, 지금 이미 detail Screen에 와 있는데, 다시 detail Screen으로 가는 navigate 함수를 썼다고 해보자.
위에서는 따로 다른 정보를 보내는 행위가 없기 때문에 구분이 가지 않겠지만,
해당 again 버튼을 눌러봤자 아무 일도 일어나지 않는다.
navigate라는 함수는 해당 screen으로 이동하라는 뜻을 가진 함수이다. 하지만 이미 그곳에 와있으므로 아무런 기능이 작동하지 않는 것이다.
따라서 Stack에는 detailScreen이 더 쌓이지 않는다.
하지만 우리는 때에 따라서 다른 정보들을 가지고 같은 화면을 재 사용해야 하는 경우가 있을 수 있다.
이 경우에는 navigate 대신 push를 써야 한다.
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
push를 쓰면 detail이란 화면을 새로운 정보를 가지고 한번 더 이동하겠다는 뜻이다. 따라서 해당 버튼을 누를수록 Stack에 detailScreen이 계속 쌓인다.
https://reactnavigation.org/docs/navigating <참고>
e. 뒤로 가기 버튼
일반적으로 Stack Navigator가 기본적으로 제공하는 Screen header를 쓸 경우, Screen 화면 좌측 상단에 뒤로 가기 버튼이 기본 제공된다. 해당 버튼을 누르면 Stack에 쌓인 이전 화면으로 돌아가고, 현재 화면은 pop되어 사라진다.
만약 버튼을 따로 커스터마이징 해서 만들어야 한다면 goBack()함수를 이용하면 된다.
<Button title="Go back" onPress={() => navigation.goBack()} />
만약 맨 첫 화면으로 이동하고 싶다면 navigate를 이용해 루트를 첫 화면으로 설정 하거나,
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
아니면 navigation의 popToTop이란 함수를 이용하면 된다. 해당 함수는 Stack 맨 밑바닥의 컴포넌트를 제외한 모든 컴포넌트를 pop 하여 없앤다.
<Button
title="Go back to first screen in stack"
onPress={() => navigation.popToTop()}
/>
3. 로직