Front-end/React Native

React Native Navigation 스크린 이동

아지송아지 2022. 2. 1. 16:10

스크린 간 이동하는 방법과 데이터를 넘기는 방법을 다루겠습니다.

 

제 내비게이터 구조는 아래와 같습니다.

  • Stack navigator
    • Intro 
    • Tab navigator
      • Home
      • List
      • Chat
      • MyPage

 

 

 

Intro -> Tab


같은 depths에 있는 intro에서 tab으로 이동하는 방법입니다.

// intro.js
import { useNavigation } from '@react-navigation/native';
...
const navigation = useNavigation();

// 함수 호출 시 탭으로 이동
const onPressMoveTab = () => {
    navigation.navigate(
        "Tab",
        {userName:"sjh"},
    );
}

 

navigate안에 스크린 이름과 전달할 데이터를 넣으면 됩니다.

navigation.navigate(스크린이름, {전달데이터})

 

전달받은 데이터를 확인하려면 route.params에 접근해야 합니다.

// tabNavigation.js
const TabNavigation = ({route}) => {

  useFocusEffect(() => {
      console.log("Tab useFocusEffect")
      console.log(route.params)
  )
  ...
}

 

 

Intro -> Tab (Chat)


서로 다른 depths 즉 tabs안에 있는 스크린으로 이동해보겠습니다.

동등한 내비게이터 안에 있는 스크린이 아니면 앞서 보여드렸던 방법으로는 이동이 불가합니다.

const onPressMoveChat = () => {
    navigation.navigate(
        "Tab",
        {
            screen:"Chat",
            userName:"sjh"
        },
    );
}

두 번째 인자에 screen이라는 key값으로 해당 내비게이터 안에서 사용하는 스크린의 이름까지 넣어주어야 합니다.

 

그렇다면 데이터를 받는 방법은 어떨까요?

이 역시 기존의 방법과는 다릅니다.

 

저희가 방금 했던 스크린의 이동은 결국 Intro -> Tab -> Chat 순서로 가기 때문에 데이터는 Tab으로 가게 됩니다.

데이터를 한 번에 넘길 수는 없을까 구글링 해보았지만 공식문서에서 넘길 수 없다고 나왔있습니다.

 

Each screen in a navigator has its own params​
For example, any params passed to a screen in a nested navigator are in the route prop of that screen and aren't accessible from a screen in a parent or child navigator.

If you need to access params of the parent screen from a child screen, you can use React Context to expose params to children.

만약 넘기고 싶다면 Context를 사용하라고 나와있었지만 그렇게 되면 작업이 많아져서 다른 방법을 찾았습니다.

 

Tab에서 받은 데이터를 Chat에 props로 넘기는 형식입니다.

 

// tabNavigation.js
const TabNavigation = ({route}) => {
  return (
      <Tab.Navigator
        screenOptions={{
          headerShown: false
        }}
      >
        <Tab.Screen name='Home' component={Home}/>
        <Tab.Screen name='List' component={List} />
        <Tab.Screen name='Chat' component={() => <Chat userName={route.params.userName}/>}/>
        <Tab.Screen name='MyPage' component={MyPage}/>
      </Tab.Navigator>
  );
};

작동은 하지만 warning이 뜹니다.

"looks like you're passing an inline function for 'component' prop for the screen"

공식문서를 찾아보니 props로 넘기려면 아래와 같은 방식으로 넘겨야 합니다.

// tabNavigation.js
const TabNavigation = ({route}) => {
  return (
      <Tab.Navigator
        screenOptions={{
          headerShown: false
        }}
      >
        <Tab.Screen name='Home' component={Home}/>
        <Tab.Screen name='List' component={List} />
        <Tab.Screen name='Chat'>
          {() => <Chat userName={route.params.userName}/>}
        </Tab.Screen>
        <Tab.Screen name='MyPage' component={MyPage}/>
      </Tab.Navigator>
  );
};

 

warning 제거하려고 문서를 살펴보니 이러한 콜백 형식으로 작성하게 되면 기본적으로 React Naviation에서 하는 최적화가 제거된다고 합니다.

 

따라서 React Context를 권장하고 만약 콜백 형식을 사용할 경우에는 React.memo혹은 React.PureComponent를 사용하라고 합니다.

 

글 마치겠습니다.

감사합니다!! :)

 

참고 :

https://reactnavigation.org/docs/nesting-navigators/

https://reactnavigation.org/docs/nesting-navigators/

https://stackoverflow.com/questions/49826920/how-to-navigate-between-different-nested-stacks-in-react-navigation

https://reactnavigation.org/docs/hello-react-navigation/#passing-additional-props
https://github.com/react-navigation/react-navigation/issues/8517