[react native] Stack Navigation

강인호·2022년 11월 19일
0

개인저장

목록 보기
64/87

참고링크
참고링크2

react-native에서 가장 중요하면서 기본이 되는 navigation을 공부했다.

처음에는 단순히 router-dom이랑 비슷한줄 알았는데 생각보다 복잡했다.

뭐가 막히는지 계속 들여다 보고 시도해보면서 나름대로의 규칙을 파악하려고 최대한 노력했다.

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import TestApp from './page/TestApp';
import TestDetail from './page/TestDetail';

export type RootStackParamList = {
  Home: undefined;
  Detail: {
    id: number;
  };
};

export default function App() {
  const Stack = createNativeStackNavigator<RootStackParamList>();
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName='Home'>
      <Stack.Screen name='Home' component={TestApp} />
      <Stack.Screen name='Detail' component={TestDetail} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
  • 타입스크립트일때는 타입을 따로 선언해준다.
export type RootStackParamList = {
  Home: undefined;
  Detail: {
    id: number;
  };
};

Screen 컴포넌트의 이름과 해당 컴포넌트에 인자로 넘겨질 params값을 정의할 수 있다.

(Home은 인자가 없고 Detail로 넘길때는 숫자열의 id값을 인자로 넘길 수 있다.)

export type RootStackParamList = {
  Home: undefined;
  Detail: {
    id: number;
  } | undefined;
};

위와 같이 union타입을 설정해주면 넘겨줄 인자가 없을때에도 에러가 발생하지 않는다.

  • Stack 객체를 만든다.
  const Stack = createNativeStackNavigator<RootStackParamList>();
  • NavigationContainer 로 감싼다.

  • 각각의 컴포넌트를 Stack.Screen의 형식으로 넣는다.

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName='Home'>
      <Stack.Screen name='Home' component={TestApp} />
      <Stack.Screen name='Detail' component={TestDetail} />
      </Stack.Navigator>
    </NavigationContainer>
  );

여기서 initialRouteName은 맨 처음 나올 스크린을 지정하고

name은 말 그대로 스크린의 name, component는 출력할 컴포넌트

맨 위에 기본적으로 name에 따른 header가 표시되는데

    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen
          name="Home"
          component={TestApp}
          options={{ headerShown: false }}
        />
        <Stack.Screen
          name="Detail"
          component={TestDetail}
          options={{ headerShown: false }}
        />
      </Stack.Navigator>
    </NavigationContainer>

이런식으로 옵션을 추가해줘서 없앨 수 있다.

여기까지는 기본 라우터돔이랑 크게 다르지 않아서 수월했으나 컴포넌트에서 navigation,route객체를 받아오는데

어려움이 생겼고 나름대로 최대한 규칙들을 정리해보자면 (정확하지 않을 수 있음)

import React from 'react';
import { RootStackParamList } from '../App';
import { StackScreenProps } from '@react-navigation/stack';

export type HomeScreenProps = StackScreenProps<RootStackParamList, 'Home'>;

function TestApp({ navigation, route }: HomeScreenProps) {

  const TextHandler = (enteredText: string) => {
    setText(enteredText);
  };
  return (
    <View>
      <View>
        <Button
          title="Go Detail"
          onPress={() => navigation.navigate('Detail', { id: 1 })}
        />
      </View>
    </View>
  );
}
export default TestApp;
  • app.tsx에서 정의한 RootStackParamList import해온다.

  • navigation과 route객체를 받아오는데 이 타입을 StackScreenProps으로 지정해주어야 한다.

  • 제네릭의 첫번째 인자로 RootStackParamList을 받고 두번째 인자로 RouteName을 받는다.

여기서 navigation은 navigation action을 실행할 수 있는 함수를 가지고있다.

() => navigation.navigate('Detail', { id: 1 })

의 형식으로 이동이 가능하다.

여기서 막혔었던게 만약 param값을 넘겨주게 설정을 했다면 무조건 넘겨야한다.

처음에는 익숙하지 않아서 디테일로 이동하려고

() => navigation.navigate('Detail')

라고 썼는데 계속 에러콘솔이 나서 머리 박아본 결과 param값을 설정해놓고 넘겨주지 않아서 발생한 오류

(타입스크립트가 개발단계에서 이런 문제점을 잡아낼 수 있다는게 좋은듯??)

이럴경우에는 위에 처럼 union타입으로 undefined을 지정하거나 2번째 인자로 해당하는 param값을 형식에 맞게 넣어주면 된다.

route에는 해당 screen의 정보가 들어있다.

key name params의 값이 들어있다.


처음에 머리가 터질것만 같았는데 계에에에에에속 보다보니까 조금씩 보이는 것 같다.

0개의 댓글