My Boundary As Much As I Experienced

ReactNative) React Navigation으로 라우터 초기 세팅하기 본문

FrontEnd/React Native

ReactNative) React Navigation으로 라우터 초기 세팅하기

Bumang 2024. 5. 29. 17:31

1. 타입으로 네비게이터의 타입을 지정해줘야 한다. (패러미터를 미리 설정)

네비게이터에는 BottomTabNavigator와 StackNavigator가 있다.

바텀탭은 쉽게 말하면 앱 아래 있는 바텀 네비게이션으로 이동할 수 있는 루트단인 것이다.

 

stack은 말 그대로 depth가 계속 진행될수록 쌓이고 쌓이는 구조이다.

아래처럼 초록 페이지에서 액션을 일으켜 다른 페이지를 키면 다른 페이지가 overlay되어 나오고,

뒤로가기를 누르면 위에 쌓인 페이지가 pop되면서 사라지고 아래 포개어져 있던 페이지가 나오는 구조이다.

 

이때 전 페이지의 state나 진행상태등은 (웹과 달리) 모두 살아있다!

모바일에서 페이지의 이동이란, stack에 쌓이는 스크린이라는 것을 기억하자.

하여튼 이 스크린들을 관리하는 Navigator에서 사용할 params들을 미리 지정한다.

// 탭들이 먼저 있고
// 탭 안에서 스택이 들어있는...
// 페이지들을 만들어 놓는 것이다.
// 로그인 하고 접근할 수 있는 곳
export type LoggedInParamList = {
  Orders: undefined; // [1]주문화면
  Settings: undefined; // [-]설정
  Delivery: undefined; // [2]지도
  Complete: {orderId: string}; // [3]배달완료(사진 찍기) // 왜 파라미터인가? => 뭘 완료하는지. orderId를 써야하기 때문에.
};

// LoggedInParamList와 나눠놓은 이유는 '감'과 '경험'임.
// 로그인 안 하고 접근할 수 있는 곳
export type RootStackParamList = {
  SignIn: undefined; // 로그인
  SignUp: undefined; // 회원가입
};

 

 

 

2. BottomTab Navigator(Tab)과 Stack Navigator를 만든다. 이때 위에서 만든 타입을 넣어 params의 타입들을 지정한다.

 

웹에서 주로 쓰는 React-Router는 패러미터를 찾을 수 없으면 자동적으로 404페이지로 가는데

React Navigation은 미리 활용한 패러미터들이 무엇인지, 타입은 뭔지 다 지정해서 초기값을 설정해줘야하는게 신기하다.

(웹과 모바일의 차이 때문인지 찾아봤는데, 그냥 React Navigation 팀의 철학 때문에 이런 구조가 나온거 같다.)

const Tab = createBottomTabNavigator<LoggedInParamList>(); // 아까 만든 LoggedInParamList 타입.
const Stack = createNativeStackNavigator<RootStackParamList>(); // 아까 만든 RootStackParamList 타입.

 

 

3. NavigationContainer에 BottomTab, Stack 네비게이터들을 제공한다.

- 아래 코드에선 isLoggedIn의 여부에 따라 TabNavigator인지 StackNavigator인지가 나뉜다.

- Screen에서 option 속성을 이용하여 스크린타이틀이나 헤더 여부 등을 조절할 수 있다.

import {NavigationContainer} from "@react-navigation/native";

...

const Tab = createBottomTabNavigator<LoggedInParamList>(); // 아까 만든 LoggedInParamList 타입.
const Stack = createNativeStackNavigator<RootStackParamList>(); // 아까 만든 RootStackParamList 타입.

  return (
    <NavigationContainer>
      {isLoggedIn ? (
        // 로그인 했으면
        <Tab.Navigator>
          <Tab.Screen
            name="Orders"
            component={Orders}
            options={{title: "오더 목록"}}
          />
          <Tab.Screen
            name="Delivery"
            component={Delivery}
            options={{headerShown: false}} // option에서 헤더를 감출 수 있다.
          />
          <Tab.Screen
            name="Settings"
            component={Settings}
            options={{title: "내 정보"}}
          />
        </Tab.Navigator>
      ) : (
        // 로그인 안 했으면
        <Stack.Navigator>
          <Stack.Screen
            name="SignIn"
            component={SignIn}
            options={{title: "로그인"}}
          />
          <Stack.Screen
            name="SignUp"
            component={SignUp}
            options={{title: "회원가입"}}
          />
        </Stack.Navigator>
      )}
    </NavigationContainer>
  );
}

export default AppInner;

 

자, 이렇게 리액트네이티브의 리액트 네비게이션으로 Router를 조립하는 방법을 알아보았다.

그러나 사실 모바일 뷰는 바텀탭 하나만으로 사용할 수 있지 않다.

BottomTab Navigator에서 stack Navigator로 쌓아두는게 필요하다.

 

 

*BottomTab의 페이지에 component props으로 stack을 지정

탭에 쓸 Stack들을 구성한다. (함수형 컴포넌트면 충분하다.)

function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

function SettingsStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Settings" component={SettingsScreen} />
      <Stack.Screen name="Profile" component={ProfileScreen} />
    </Stack.Navigator>
  );
}

 

바텀탭에 component prop로 미리 만들어둔 탭용(?) Stack들을 제공한다.

단순 Page를 제공하는게 아니라, stack 컴포넌트 자체를 제공해도 괜찮다.

function MyTabs() {
  return (
    <Tab.Navigator>
      // component 속성에 미리 만들어둔 stack들을 제공한다.
      <Tab.Screen name="Home" component={HomeStack} />
      <Tab.Screen name="Settings" component={SettingsStack} />
    </Tab.Navigator>
  );
}

 

여담으로 Screen 컴포넌트들은 props로 컴포넌트를 제공했을 때 특수한 처리가 되어

반환되는 컴포넌트니 고차 컴포넌트HOC라 볼 수 있겠다.(뇌피셜)