I am new to React and TypeScript and I created an app with Expo Go that contains the React Bottom Tab Navigator (https://reactnavigation.org/docs/bottom-tab-navigator/). My problem is that the example does not define the types for the {navigation}
parameter and I would like to solve this.
Note: it works without defining the type, but I would like to learn and understand how to fix it…
I have a Navigation.tsx
containing my root stack and the tabs (I hope I limited it to the relevant parts)
const Stack = createNativeStackNavigator();
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList { }
}
}
type RootStackParamList = {
Tabs: NavigatorScreenParams<RootTabParamList> | undefined;
Modal: undefined;
NotFound: undefined;
};
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>;
const BottomTab = createBottomTabNavigator<RootTabParamList>();
type RootTabParamList = {
About: undefined;
Test: undefined;
};
export type RootTabScreenProps<Screen extends keyof RootTabParamList> = CompositeScreenProps<
BottomTabScreenProps<RootTabParamList, Screen>,
NativeStackScreenProps<RootStackParamList>
>;
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
return (
<NavigationContainer
linking={LinkingConfiguration}
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}
>
<Stack.Navigator>
<Stack.Screen name="Tabs" component={BottomTabNavigator} options={{ headerShown: false }}/>
// (!) Problem line
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }}/>
<Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Modal" component={ModalScreen} />
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
);
}
I found out which is the right type for the {navigation}
in one of the tabs, e.g. About.tsx
:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Text, View } from '../ui/Components';
import { RootTabScreenProps } from '../ui/Navigation';
export default function About({ navigation }: RootTabScreenProps<'About'>) {
return (
<View style={styles.container}>
<Text style={styles.title}>About</Text>
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
<Text>/screens/About.tsx</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')}>
<Text>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
But I can’t find the right type for the {navigation}
in the root components (no tabs), like NotFound.tsx
:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Text, View } from '../ui/Components';
// (!) Problem line
export default function NotFoundScreen({ navigation }: ?????) {
return (
<View style={styles.container}>
<Text style={styles.title}>This screen doesn't exist.</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')} style={styles.link}>
<Text style={styles.linkText}>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
Without the type, I (of course) get an error in NotFound.tsx
, that
Binding element ‘navigation’ implicitly has an ‘any’ type.
I tried RootStackScreenProps<'NotFound'>
, which will let the error above disappear, but instead I get an error in Navigation.tsx
on line <Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }}/>
:
Type ‘({ navigation }: RootStackScreenProps<"NotFound">) => Element’ is not assignable to type ‘ScreenComponentType<ParamListBase, "NotFound"> | undefined’.
Type ‘({ navigation }: RootStackScreenProps<"NotFound">) => Element’ is not assignable to type ‘FunctionComponent<{}>’.
Types of parameters ‘__0’ and ‘props’ are incompatible.
Type ‘{}’ is missing the following properties from type ‘RootStackScreenProps<"NotFound">’: navigation, route
So… What is the right type to use here?
2
Answers
Thanks to the help of @phantomspooks and his answer (https://stackoverflow.com/a/76248413/4090157), I think I now understand the types a bit better.
I was finally able to resolve my problem by making the following changes:
<Screen>
fromexport type RootStackScreenProps
inNavigation.tsx
NotFound.tsx
react navigation was written in typescript, so any type you would need relating to it probably exists. Here they cover typing a Stack Navigator, and its same premises for a bottom tab navigator. You just need to export
RootStackParamList
and importBottomTabScreenProps
:And now for doing the NotFound screen: