React Navigation中CommonActions.setParams修改其他页面参数失效问题
我用MaterialTopTabNavigator构建多步骤导航,需要从Step1页面修改Step2和Step3页面的resetInputs参数,但尝试后参数始终未发生变化,以下是具体场景和代码:
导航结构代码
<NavigationContainer independent={true}> <Tab.Navigator screenOptions={{swipeEnabled: false, gestureEnabled: false,headerShown: false,}}> <Tab.Screen name="Step 1" component={Step1LenRigi} options={{title: "Step 1", gestureEnabled: false,}} initialParams={{resetInputs: false, hundlerGetRouteKeys: getRouteKeys}}/> <Tab.Screen name="Step 2" component={Step2LenRigi} options={{title: "Step 2", gestureEnabled: false,}} initialParams={{resetInputs : false, hundlerSetRouteKeys: setRouteKey}}/> <Tab.Screen name="Step 3" component={Step3LenRigi} options={{title: "Step 3", gestureEnabled: false,}} initialParams={{resetInputs : false, hundlerSetRouteKeys: setRouteKey}}/> <Tab.Screen name="Step 4" component={Step4LenRigi} options={{title: "Step 4", gestureEnabled: false,}} initialParams={{resetInputs : false}} /> </Tab.Navigator> </NavigationContainer>
Step1中尝试修改参数的代码
按照React Navigation文档指引,我用navigation.dispatch结合CommonActions.setParams尝试修改参数:
async function hundlerResetSteps(value) { /// 获取路由key const route_keys = await hundlerGetRouteKeys(); console.log("!!!!!!!!!!!!!! in route_keys : ", route_keys); /// 修改其他页面参数 navigation.dispatch({ ...CommonActions.setParams({ resetInputs: true }), source: route_keys?.step2, }); navigation.dispatch({ ...CommonActions.setParams({ resetInputs: true }), source: route_keys?.step3, }); }
Step2/3中验证参数的代码
在Step2和Step3的focus事件中,我通过三种方式打印参数,发现resetInputs始终未变化:
let { params } = useRoute(); const tmp_using_useNavigationState = useNavigationState(state => state.routes); /// 页面聚焦监听 useEffect(()=> { const unsubscribe = navigation.addListener('focus', () => { const tmp_using_getState = navigation.getState(); ; let tmp_using_route_params = route?.params || false; console.log("\n#### Focus in step 2 with tmp_using_useNavigationState: ", tmp_using_useNavigationState[1]); console.log("\n#### Focus in step 2-1 with tmp_using_getState: ", tmp_using_getState); console.log("\n#### Focus in step 2-2 with tmp_using_route_params: ", tmp_using_route_params); }); return unsubscribe; }, [route]);
依赖版本
- @react-navigation/native "^6.0.11"
- @react-navigation/bottom-tabs "^6.3.2"
- @react-navigation/material-bottom-tabs "^6.3.2"
- @react-navigation/material-top-tabs "^6.2.2"
- react-native-screens "^3.16.0"
- react-native-tab-view "^3.1.1"
- expo "~46.0.7"
- node v14.17.4
- npm: 6.14.14
问题原因分析
source参数使用错误:CommonActions.setParams的source字段是指定发起动作的来源路由key,而非目标路由key。要修改Step2/3的参数,应该用target字段指定目标路由的key。- 路由key获取准确性存疑:需要确认
hundlerGetRouteKeys()返回的route_keys?.step2和route_keys?.step3确实是Step2/3页面的正确路由key。 useRoute引用未实时更新:Step2/3中route对象在组件初始化时被捕获,即使参数更新,依赖route的useEffect可能因引用未变而不触发重新渲染,导致获取的参数不是最新值。
解决办法
1. 修正setParams的dispatch写法
将source替换为target,指定目标路由key:
async function hundlerResetSteps(value) { const route_keys = await hundlerGetRouteKeys(); // 修改Step2参数 navigation.dispatch({ ...CommonActions.setParams({ resetInputs: true }), target: route_keys?.step2, // 改用target指定目标路由 }); // 修改Step3参数 navigation.dispatch({ ...CommonActions.setParams({ resetInputs: true }), target: route_keys?.step3, }); }
2. 确保路由key正确获取
可通过navigation.getState()直接获取各页面路由key,示例函数:
// 获取路由key的示例函数 function getRouteKeys() { const state = navigation.getState(); return { step1: state.routes.find(r => r.name === "Step 1")?.key, step2: state.routes.find(r => r.name === "Step 2")?.key, step3: state.routes.find(r => r.name === "Step 3")?.key, step4: state.routes.find(r => r.name === "Step 4")?.key, }; }
3. 修正Step2/3中参数获取方式
在focus事件中直接获取最新的路由参数,更新useEffect依赖:
// Step2/3中的代码修改 const navigation = useNavigation(); const route = useRoute(); useEffect(()=> { const unsubscribe = navigation.addListener('focus', () => { // 获取最新参数 const latestParams = route.params; console.log("#### Step2最新参数: ", latestParams); // 或通过navigation.getState()查找对应路由 const state = navigation.getState(); const step2Route = state.routes.find(r => r.name === "Step 2"); console.log("#### Step2路由参数: ", step2Route?.params); }); return unsubscribe; }, [navigation, route]); // 添加navigation和route到依赖列表
4. 替代方案:使用全局状态管理
如果导航参数修改仍有问题,建议用Context或Redux维护全局状态,避免依赖导航参数传递:
// 创建Context import { createContext, useContext, useState } from 'react'; const ResetContext = createContext(); // 封装Provider function ResetProvider({ children }) { const [resetStates, setResetStates] = useState({ step2: false, step3: false, }); const resetSteps = () => { setResetStates({ step2: true, step3: true, }); }; return ( <ResetContext.Provider value={{ resetStates, resetSteps }}> {children} </ResetContext.Provider> ); } // Step1中调用修改方法 const { resetSteps } = useContext(ResetContext); async function hundlerResetSteps(value) { resetSteps(); } // Step2/3中读取状态 const { resetStates } = useContext(ResetContext); useEffect(()=> { const unsubscribe = navigation.addListener('focus', () => { console.log("#### Step2 resetInputs: ", resetStates.step2); }); return unsubscribe; }, [resetStates]);
内容的提问来源于stack exchange,提问作者Oussama Nm
相关产品推荐
相关产品推荐

