PUROGU LADESU

ポエムがメインのブログです。

【ReactNative】ReactNavigationでparamsが渡せなくてハマった

名前はちゃんとつけよう

navigation.navigateで画面遷移時にパラメータを渡そうと思ったが、画面遷移はするもものparamsが渡らなくて数時間ハマった件。

結論から言うと、同じ名前のルーティングがあったせいで別のところに遷移していたのが原因でした。

基本的にStackNavigatorの中にScreenを入れる構造にしていたのだが、別のStackへ遷移する場合 Stack -> Screen のように指定しないといけない。フォルダパスと同じですね。

navigation.navigate('RegisterStack', {
  screen: 'RegisterScreen',
  params: { test: 'aaaaa' },
})

Nesting navigators | React Navigation

ところがStackとScreenが同じ名前になっていたからややこしい。画面遷移は間違ってStackの方にしても内包するScreenが自動的に表示される見た目の違和感はない。だが当然paramsもガッツリStackの方に渡していることになるため、Screenで値が取れなかったということのようです。

階層を意識しよう

ネストする場合はTabとかStackとかDrawerも含めてちゃんと名前をつけて図を書いたほうが良いです。

確認用サンプル

import React from 'react';
import { Button, View, Text } from 'react-native';
import { createStackNavigator } from '@react-navigation/stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

function ScreenA_2({ route, navigation }) {
  const { user } = route.params || {};
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>ScreenA_2 Screen</Text>
      <Text>userParam: {JSON.stringify(user || {})}</Text>
      <Button
        title="Go to ScreenA_1"
        onPress={() => navigation.navigate('ScreenA_1')}
      />
    </View>
  );
}

function ScreenA_1({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>ScreenA_1 Screen</Text>
      <Button
        title="Go to ScreenB1"
        onPress={() => navigation.navigate('ScreenB_1', { user: 'david' })}
      />
    </View>
  );
}

function ScreenB_1({ route, navigation }) {
  const { user } = route.params || {};
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>ScreenB_1 Screen</Text>
      <Text>userParam: {JSON.stringify(route.params?.user || {})}</Text>
      <Button
        title="Go to ScreenA_1"
        onPress={
          // () => navigation.navigate('ScreenA_1', { user: 'jane' })
          () =>
            navigation.navigate('StackNavA', {
              screen: 'ScreenA_1',
              params: { user: 'jane' },
            })
        }
      />
    </View>
  );
}

function ScreenB_2({ route, navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>ScreenB_2Screen</Text>
    </View>
  );
}

const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
const Stack2 = createBottomTabNavigator();

function StackNavA() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="ScreenA_1" component={ScreenA_1} />
      <Stack.Screen name="ScreenA_2" component={ScreenA_2} />
    </Stack.Navigator>
  );
}

function StackNavB() {
  return (
    <Stack2.Navigator>
      <Stack.Screen name="ScreenB_1" component={ScreenB_1} />
      <Stack.Screen name="ScreenB_2" component={ScreenB_2} />
    </Stack2.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator initialRouteName="StackNavB">
        <Drawer.Screen name="StackNavA" component={StackNavA} />
        <Drawer.Screen name="StackNavB" component={StackNavB} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}