React Navigation嵌套导航器中useNavigation的类型定义方案
问题根源
子组件NavigateButton中的useNavigation默认获取的是顶层RootStack导航的类型,而顶层路由列表中不存在ScreenB,因此TypeScript报错。我们需要让useNavigation自动推断当前所在的ChildStackA栈的导航类型。
解决方案(满足所有要求)
方案1:简化ScreenA的Props类型(无需访问父级导航时使用)
如果ScreenA不需要跳转至父级栈(比如ChildStackB),直接使用当前栈的StackScreenProps即可让useNavigation自动推断类型:
// ScreenA.tsx import type { StackScreenProps } from '@react-navigation/stack'; import type { ChildStackAParamList } from './ChildNavigatorA'; // 仅保留当前栈的屏幕Props类型 type ScreenAProps = StackScreenProps<ChildStackAParamList, 'ScreenA'>; export const ScreenA = ({ navigation }: ScreenAProps) => { return ( <View style={styles.view}> <Text style={styles.text}>Screen A</Text> <NavigateButton /> </View> ); }; const NavigateButton = () => { const { navigate } = useNavigation(); // 此时TypeScript可正确推断'ScreenB'为合法路由 return <Button title="To ScreenB" onPress={() => navigate('ScreenB')} />; };
方案2:保留父级导航访问(使用CompositeScreenProps时)
如果需要在ScreenA中同时操作当前栈和父级栈,可封装自定义导航钩子避免直接给useNavigation加泛型:
- 创建自定义钩子文件:
// hooks/useChildStackANavigation.ts import { useNavigation } from '@react-navigation/native'; import type { StackNavigationProp } from '@react-navigation/stack'; import type { ChildStackAParamList } from '../ChildNavigatorA'; // 内部封装泛型,对外暴露无泛型的钩子 export const useChildStackANavigation = () => useNavigation<StackNavigationProp<ChildStackAParamList>>();
- 在ScreenA的子组件中使用该钩子:
// ScreenA.tsx import { useChildStackANavigation } from './hooks/useChildStackANavigation'; // 保留原CompositeScreenProps以支持父级导航操作 type ScreenAProps = CompositeScreenProps< StackScreenProps<ChildStackAParamList, 'ScreenA'>, CompositeScreenProps< StackScreenProps<ModalStackParamList>, StackScreenProps<RootStackParamList> > >; export const ScreenA = ({ navigation }: ScreenAProps) => { return ( <View style={styles.view}> <Text style={styles.text}>Screen A</Text> <NavigateButton /> </View> ); }; const NavigateButton = () => { const { navigate } = useChildStackANavigation(); return <Button title="To ScreenB" onPress={() => navigate('ScreenB')} />; };
验证全局命名空间定义
确保全局路由类型定义正确,无需修改:
// RootNavigator.tsx export type RootStackParamList = { ModalNavigator: NavigatorScreenParams<ModalStackParamList>; }; declare global { namespace ReactNavigation { interface RootParamList extends RootStackParamList {} } }
内容的提问来源于stack exchange,提问作者MissingSemicolon
相关产品推荐
相关产品推荐

