如何正确重置React Navigation导航状态解决已删产品详情页报错
错误原因
- 你的导航是嵌套结构:根节点是
DrawerNavigator,下属两个独立的StackNavigator(产品流程栈、管理流程栈),ProductDetail页面属于产品流程栈的路由 - 你在管理流程页面调用
navigation.dispatch时,拿到的state是当前管理流程栈的状态,根本不包含产品流程栈的路由,所以你过滤不掉属于另一个栈的ProductDetail页面 - 报错
TypeError: undefined is not an object (evaluating 'action.target')的直接原因是:React Navigation 6+在嵌套导航中执行reset操作时,需要指定要操作的导航器的target属性,你没有传入该属性
解决方案
方案1:修改根导航状态过滤所有ProductDetail路由(符合你最初的思路)
给你的根DrawerNavigator设置唯一id,比如:
<Drawer.Navigator id="RootDrawer"> {/* 你的两个栈屏幕 */} </Drawer.Navigator>
删除产品时操作根导航的状态,遍历所有子栈过滤详情页路由:
// 拿到根导航实例 const rootNav = navigation.getParent('RootDrawer'); rootNav.dispatch(state => { const processedRoutes = state.routes.map(rootRoute => { // 处理每个子栈的路由列表 if (rootRoute.state?.routes) { return { ...rootRoute, state: { ...rootRoute.state, routes: rootRoute.state.routes.filter(r => r.name !== 'ProductDetail') } } } return rootRoute; }) return CommonActions.reset({ ...state, routes: processedRoutes, index: state.index, // 保持当前激活的栈不变 target: state.key // 传入target避免报错 }) })
方案2:详情页加防御逻辑(更简单易维护)
不用修改导航状态,直接在ProductDetail页面判断产品是否存在,不存在则自动退回:
// ProductDetail 页面代码 import { useSelector } from 'react-redux'; // 如果你用其他全局状态库替换对应取值逻辑即可 import { useNavigation, useFocusEffect } from '@react-navigation/native'; const ProductDetail = () => { const navigation = useNavigation(); // 从全局状态取当前详情页的产品数据 const currentProduct = useSelector(state => state.products.list.find(p => p.id === route.params.productId)); // 页面聚焦时判断产品是否存在 useFocusEffect( React.useCallback(() => { if (!currentProduct) { navigation.goBack(); // 也可以跳转到产品列表页:navigation.navigate('ProductList') } }, [currentProduct, navigation]) ); // 渲染时加兜底 if (!currentProduct) { return null; // 也可以渲染友好提示:<View><Text>该产品已被删除</Text></View> } // 原有正常渲染逻辑 return (/* 你的页面内容 */) }
临时解决当前报错的方法
如果你只是要先解决action.target的报错,只需要在reset参数里加上target: state.key即可:
navigation.dispatch(state => { const routes = state.routes.filter( route => route.name !== 'ProductDetail', ); return CommonActions.reset({ ...state, routes: routes, target: state.key // 新增这行即可消除报错 }); });
注意:这个方法只能解决报错,不能实现你过滤另一个栈中详情页的业务需求
内容的提问来源于stack exchange,提问作者abdou-tech
相关产品推荐
相关产品推荐

