'Type error in getting route params within nested navigator using Typescript [react-navigation v6]
Having a navigation type definition as bellow, when I navigate from e.g AOne
to BTwo
with id:99
the console log of props.route.params
shows correct info. But props.route.params.id
throws type error
TypeError: undefined is not an object (evaluating 'props.route.params.id')
// navigation related imports in all components
import {BottomTabScreenProps} from '@react-navigation/bottom-tabs';
import {CompositeScreenProps, NavigatorScreenParams} from '@react-navigation/core';
import {StackScreenProps} from '@react-navigation/stack';
// type defenitions
export type StackOneParams = {
AOne:undefined,
BOne: undefined,
// some other screens
};
export type StackTwoParams = {
ATwo: undefined;
BTwo:{id:number};
// some other screens
};
export type TabParams = {
StackOne: NavigatorScreenParams<StackOneParams>;
StackTwo: NavigatorScreenParams<StackTwoParams>;
// ... some other stacks each represent a tab
};
export type RootParamList = {
ROne: undefined; // these screens should stand alone and not blong to any tab
RTwo: undefined;
Tabs: NavigatorScreenParams<TabParams>
}
// navigation from AOne to BTwo
props.navigation.navigate('Tabs', {
screen: 'StackTwo',
params: {screen: 'BTwo', params: {id: 99}}
}); // this part give correct auto complete hints in VSCode and no compilation error
// BTwo component (screen)
//--------------------------------
type Props = CompositeScreenProps<
StackScreenProps<RootParamList, 'Tabs'>,
CompositeScreenProps<
BottomTabScreenProps<TabPrams, 'StackTwo'>,
StackScreenProps<StackTwoParams, 'BTwo'>
>
>;// using CompositeScreenProps to be able to navigate to screens in another tabs
// otherwise just `type Props=StackScreenProps<StackTwoParams, 'BTwo'>` works fine but cannot navigate to other tabs
const BTwo:React.FC<Props> = (props) =>{
console.log(props.route.params)// the log shows {id:23}
// but props.route.params.id gives error and also no auto completion hint
return(...)
}
- is this the correct way to define screen props for a specific screen, like what I have in BTwo screen? or the sequence of the composition should be different?
most of the examples (and the official documentation) show the most simple composition where the target screen is not even in second level of nesting (in the official doc profile
is not really in nested bottom tabs)
How should I solve the type error in this case?
the image shows the VSCode auto-complete suggestions
Solution 1:[1]
Solution using CompositeScreenProps
My other explanations were not quite accurate. The way you have defined the CompositeScreenProp
is not correct. Here is the correct way to implement this.
type ScreenProps = CompositeScreenProps<
StackScreenProps<StackTwoParams, "BTwo">,
CompositeScreenProps<
BottomTabScreenProps<TabParams, "StackTwo">,
StackScreenProps<RootParamList>
>
>
The first parameter of CompositeScreenProps
contains the type of the navigator that owns the screen. In this case BTwo
is owned by StackTwo
and this determines the primary navigator, which is a Stack
.
The above yields to the correct types as well.
const BTwo = (props: ScreenProps) => {
return <></>
}
Solution using separate types for navigation and route
We can type the navigation object and the route object separately as follows.
type NavigationProps = CompositeNavigationProp<
StackNavigationProp<StackTwoParams, "BTwo">,
CompositeNavigationProp<
BottomTabNavigationProp<TabParams, "StackTwo">,
StackNavigationProp<RootParamList>
>
>
type ScreenPropsA = {
navigation: NavigationProps
route: RouteProp<StackTwoParams, "BTwo">
}
Notice the usage of CompositeNavigationProp
and RouteProp
here.
Then, use it as follows.
const BTwo = ({ route, navigation }: ScreenProps) => {
return <></>
}
Both, route
and navigation
are now correctly typed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |