ReactNativeのNavigationOptionをTypeScriptでいい感じに使う
NativeStackNavigatorの例。
import React from 'react';
import { Platform } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import CategoriesScreen from '../screens/CategoriesScreen';
import CategoryMealsScreen from '../screens/CategoryMealsScreen';
import MealDetailScreen from '../screens/MealDetailScreen';
import Colors from '../constants/Colors';
import { CATEGORIES } from '../data/dummy-data';
export type RootStackParamList = {
Categories: undefined;
CategoryMeals: { categoryId: string };
MealDetail: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
const MealsNavigator = () => (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Categories"
screenOptions={{
headerStyle: {
backgroundColor: Platform.OS === 'android' ? Colors.primary : '',
},
headerTintColor: Platform.OS === 'android' ? 'white' : Colors.primary,
}}
>
<Stack.Screen
name="Categories"
component={CategoriesScreen}
options={{
headerTitle: 'Meal Categories',
}}
/>
<Stack.Screen
name="CategoryMeals"
component={CategoryMealsScreen}
options={(props) => ({
title: CATEGORIES.find((c) => c.id === props.route.params.categoryId)
?.title,
})}
/>
<Stack.Screen name="MealDetail" component={MealDetailScreen} />
</Stack.Navigator>
</NavigationContainer>
);
export default MealsNavigator;
他のScreenからいい感じに使えるようにするポイントはここ
export type RootStackParamList = {
Categories: undefined;
CategoryMeals: { categoryId: string };
MealDetail: undefined;
};
他のScreenからはこうやって使える。ポイントは NativeStackScreenProps
に RootStackParamList
を渡してることと、第2引数に自分のScreen名を渡していること。これでルートパラメータも補完がきく。
interface Props
extends NativeStackScreenProps<RootStackParamList, 'CategoryMeals'> {}
const CategoryMealsScreen: React.FunctionComponent<Props> = (props) => {
デフォルトの ScreenOption
は Stack.Navigator
の screenOptions
にて設定できる。
詳細な情報ありがとうございます。この記事のお陰で物凄く助かりました。native-stack に関しては問題なく TypeScript 化できました。
ちょっと今困っているのは drawer の TypeScript 化で、下記の部分で TypeScript のエラーが出ます。
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
上記で Drawer.Navigator が JSX として使えないと言うエラーが表示されます。
'Drawer.Navigator' cannot be used as a JSX component.
ただし、マトモに動くようで、TypeScript のエラー表示だけの問題です。
もし何か思い当たる節がございましたら、ご教授頂ければ幸いです。
Package の中身を追いかけたのですが、どうもバグっぽいので、下記の issue を react navigation に上げておきました。
'Drawer.Navigator' cannot be used as a JSX component with TypeScript #10507
速攻で reply をもらって、解決しました。原因は @types/react package が複数インストールされており、その内の一つを yarn remove して 上記の現象がなくなりました。因みに yarn why @types/react で調べて、yarn remove @types/react で消しました。只、@types/react を私が明示的にインストールした訳ではなく、React Native の環境を作る時に混在したようです。