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' }}>