React Native中如何处理‘NAVIGATE未被导航器处理’错误
问题情况
碰到了导航未处理的错误,试了两种办法都没用:
- 按文档配了
NotFound: '*'的路由规则,没生效 - 用ErrorBoundary包了导航器,能抓其他错误但抓不到导航错误
相关代码如下:
路由配置代码
const config = { screens: { Home: { initialRouteName: 'Feed', screens: { Profile: 'users/:id', }, }, NotFound: '*', }, };
App.js代码
const App = () => { const config = {...} return ( <NotificationsProvider> <Navigator linking={linking}/> </NotificationsProvider> ); }
Navigator.js代码
<NavigationContainer ref={navigationRef} linking={linking}> <MyStack /> </NavigationContainer>
MyStack代码
const MyStack = () => { return ( <ErrorBoundary FallbackComponent={FallbackWithoutReset} onError={onError} navigation={navigation} > <Stack.Navigator navigation={navigation}> <Stack.Group> ... </Stack.Group> <Stack.Group> </Stack.Screen> <Stack.Screen name="Settings" component={SettingsScreen} /> </Stack.Group> ... <Stack.Screen name="NotFound" component={NotFoundScreen} /> </Stack.Navigator> </ErrorBoundary> ) }
解决办法
1. 修复路由规则不生效的问题
你把NotFound: '*'的位置放错了,得放在根级screens的最后一位,同时要保证linking对象正确整合了这个配置,而且导航栈里确实有NotFound页面。
改一下路由配置,确保通配符路由在最后:
const config = { screens: { Home: { initialRouteName: 'Feed', screens: { Profile: 'users/:id', }, }, // 必须放在所有路由后面 NotFound: '*', }, }; // 正确创建linking对象 const linking = { prefixes: ['yourapp://'], // 换成你自己的App前缀 config, };
另外检查下NavigationContainer有没有正确传linking属性,你的Navigator.js里已经传了,但要确认linking对象确实包含上面的config。
2. 搞定ErrorBoundary抓不到导航错误的问题
React Navigation的导航错误属于异步错误,默认的React ErrorBoundary抓不到异步错误。要处理这种错误,得用NavigationContainer自带的onUnhandledAction回调:
修改Navigator.js:
const handleUnhandledAction = (action, state) => { // 处理未被识别的导航动作,直接跳转到NotFound页面 if (action.type === 'NAVIGATE') { navigationRef.current?.navigate('NotFound'); } }; <NavigationContainer ref={navigationRef} linking={linking} onUnhandledAction={handleUnhandledAction} > <MyStack /> </NavigationContainer>
同时,ErrorBoundary别包整个导航器,应该包单个页面组件,因为导航器的错误不属于组件树的同步错误:
// 例子:在Settings页面里用ErrorBoundary const SettingsScreen = () => { return ( <ErrorBoundary FallbackComponent={FallbackWithoutReset} onError={onError} > {/* 页面内容 */} </ErrorBoundary> ); };
额外要检查的点
- 确认
navigationRef已经正确初始化:
import { NavigationContainerRef } from '@react-navigation/native'; const navigationRef = React.createRef();
- 保证所有导航动作的
name参数都在栈里存在,或者通过onUnhandledAction统一处理没匹配上的情况。
内容的提问来源于stack exchange,提问作者learncode
相关产品推荐
相关产品推荐

