React Navigation v6がリリースされたので移行してみた
PR
実装
v5→v6の移行は、以下の記事を読んで進めた
https://reactnavigation.org/docs/upgrading-from-5.x/
package.jsonを更新
"@react-navigation/native": "^6.0.2", "@react-navigation/stack": "^6.0.7",
起動はそのまま行えたが、以下の箇所でwarning、typeエラーが発生していたので修正
useNavigation、createStackNavigatorにtypeの指定が必要になった
useNavigation、createStackNavigatorにtypeを指定しないで、navigateを使用するとtypeチェックでエラーになるようになった
src/components/organisms/SettingModal/SettingModal.tsx:32:25 - error TS2345: Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: never; key?: string | undefined; params: never; merge?: boolean | undefined; }'. 32 navigation.navigate('SettingLicence');
以下みたいに、typeを設定すればエラーにならなくなります
import { RootStackParamList } from 'lib/navigation'; import { RouteProp } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { useNavigation } from '@react-navigation/native'; type ScreenNavigationProp = StackNavigationProp< RootStackParamList, 'Home' >; type ScreenRouteProp = RouteProp<RootStackParamList, 'Home'>; export type Props = { navigation: ScreenNavigationProp; route: ScreenRouteProp; }; const SettingModal: React.FC<Props> = (props) => { const navigation = useNavigation<HomeScreenNavigationProp>();
Stack.Groupを使用する
v5までだと、各画面のまとまり毎にStack.NavigatorでWrapするような作りでしたが、v6からその作りだと以下みたいなwarningが発生する
Found screens with the same name nested inside one another. Check: Home, Home > Home This can cause confusing behavior during navigation. Consider using unique names for each screen instead. at node_modules/@sentry/utils/dist/instrument.js:111:20 in <anonymous> at src/Router.tsx:5:0 in <global> at node_modules/@react-navigation/core/src/useOnAction.tsx:135:9 in React.useCallback$argument_0
こちらの対処方法は、Stack.Groupを使用すればOK。 修正的には以下のようになる。
■ 修正前
<Stack.Navigator initialRouteName="Home" mode="modal"> <Stack.Screen name="Home" component={Home} options={{ headerShown: false }} /> <Stack.Screen name="MyPage" component={MyPage} options={{ headerShown: false }} /> </Stack.Navigator>
で↑のMyPageのコンポーネント内で更に以下を実装していた。
■ src/components/pages/MyPage/index.tsx
const Stack = createStackNavigator<RootStackParamList>(); const RootStack = () => { return ( <Stack.Navigator initialRouteName="MyPage"> <Stack.Screen name="MyPage" component={MyPage} options={MyPageScreenOption('マイページ')} /> <Stack.Screen name="Login" component={Login} options={MyPageScreenOption('サインイン')} /> <Stack.Screen name="UpdateProfile" component={UpdateProfile} options={MyPageScreenOption('プロフィール編集')} /> <Stack.Screen name="SettingAddShareUser" component={SettingAddShareUser} options={MyPageScreenOption('共有メンバー追加')} /> <Stack.Screen name="SettingRelationshipRequests" component={SettingRelationshipRequests} options={MyPageScreenOption('共有メンバー申請')} /> <Stack.Screen name="SettingAcceptedRelationship" component={SettingAcceptedRelationship} options={MyPageScreenOption('')} /> </Stack.Navigator> ); }; export default RootStack;
このコードが修正後は以下の通りになった。
■ 修正後
<Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" component={Home} options={HomeScreenOption()} /> <Stack.Group screenOptions={{ presentation: 'modal' }}> <Stack.Group> <Stack.Screen name="MyPage" component={MyPage} options={MyPageScreenOption('マイページ')} /> <Stack.Screen name="Login" component={Login} options={MyPageScreenOption('サインイン')} /> <Stack.Screen name="UpdateProfile" component={UpdateProfile} options={MyPageScreenOption('プロフィール編集')} /> <Stack.Screen name="SettingAddShareUser" component={SettingAddShareUser} options={MyPageScreenOption('共有メンバー追加')} /> <Stack.Screen name="SettingRelationshipRequests" component={SettingRelationshipRequests} options={MyPageScreenOption('共有メンバー申請')} /> <Stack.Screen name="SettingAcceptedRelationship" component={SettingAcceptedRelationship} options={MyPageScreenOption('')} /> </Stack.Group> </Stack.Navigator>
ナビゲーションの宣言内でStack.GroupでWrapしてあげればOKです。 ナビゲーションの書き方がシンプルになった。
modalの指定はscreenOptionsを使用する
v5ではmodalの宣言はStack.Navigatorのmodeをmodalに指定する感じでしたが、
<Stack.Navigator initialRouteName="Home" mode="modal">
v6からはscreenOptionsのpresentationにmodal'を指定する形式になった。
<Stack.Group screenOptions={{ presentation: 'modal' }}>