React Navigation v5 BottomTabNavigator如何设置动态initialRouteName
你的实现思路是正确的,在Tab.Navigator上动态设置initialRouteName是可行的,只需要修复现有代码里的useEffect逻辑问题即可实现需求。
现有代码的问题
你当前的useEffect逻辑会导致死循环:你在监听meData变化的回调里调用了fetchData,每次请求返回更新meData后又会触发新的请求,永远不会走到设置loading为false的逻辑。
修复方案
调整useEffect逻辑,拆分两个独立的副作用监听:
// 组件挂载时仅请求一次用户信息 useEffect(() => { fetchData(); }, [fetchData]); // 监听请求返回结果,更新订阅数据和加载状态 useEffect(() => { if (meData) { setSubs(meData.me.subscribes); setLoading(false); } }, [meData]);
修改完成后,加载阶段会渲染Loading组件,等用户订阅数据请求完成后才会渲染Tab.Navigator,此时initialRouteName会根据subs的长度自动选择Home或者Explorer,完全符合你的需求。
可选优化方案
如果想要减少Tab页的加载等待时间,也可以把用户信息请求提到根Stack层,在判断token存在之后先请求用户订阅数据,再将初始路由作为props传入MainNavigator:
根Stack修改示例
// 根组件中新增订阅数据相关状态 const [userSubs, setUserSubs] = useState([]); const [loadingUser, setLoadingUser] = useState(true); // 根组件中请求用户信息逻辑,token存在时触发 useEffect(() => { if (token) { // 调用请求用户信息接口 USER_ME_QUERY().then(res => { setUserSubs(res.me.subscribes); setLoadingUser(false); }) } }, [token]) // 加载中返回Loading组件 if (loadingUser && token) { return <Loading /> } return ( <Stack.Navigator headerMode="none"> {!token ? ( <Stack.Screen isSignout={isSignout} name="AuthStack" component={AuthNavigator} /> ) : ( <Stack.Screen name="HomeStack" > {props => <MainNavigator {...props} initialRoute={userSubs.length > 0 ? 'Home' : 'Explorer'} />} </Stack.Screen> )} </Stack.Navigator> )
MainNavigator简化示例
const MainNavigator = ({initialRoute}) => { return ( <Tab.Navigator initialRouteName={initialRoute} {/* 其余配置保持不变 */} > {/* 其余Tab.Screen配置保持不变 */} </Tab.Navigator> ) }
内容的提问来源于stack exchange,提问作者Prisca Aure
相关产品推荐
相关产品推荐

