React嵌套导航中HOC两种写法行为差异的底层原因咨询
两种写法行为差异的本质原因
核心差异在于**useNavigation的调用时机和它所处的React Context层级**,结合React和React Navigation的工作机制来拆解:
第一种写法:component={withBack(...)}
<Stack.Screen name="Branches" component={withBack((props) => <Branches {...props} />)} />
这里withBack是在定义Stack.Screen的阶段就执行了——也就是当你的根导航组件渲染时,withBack会被立刻调用。此时:
useNavigation会在这个时机尝试读取React Context中的导航实例- 由于当前上下文是根导航的Context(因为
Stack.Screen是在根导航容器下定义的),所以拿到的是根导航的navigation对象 - 后续点击返回按钮时,
navigation.goBack()会作用于根导航栈,自然就回到了根页面
第二种写法:component={()=> withBack(...)()}
<Stack.Screen name="Branches" component={()=> withBack((props) => <Branches {...props} />)()} />
这里component接收的是一个动态执行的函数:
- 只有当这个嵌套栈的
Branches屏幕被激活、开始渲染时,这个函数才会执行 - 函数内部调用
withBack(...)(),此时withBack里的useNavigation才会被触发,而当前的上下文是嵌套栈导航的Context(因为屏幕已经处于嵌套栈的层级中) - 因此获取到的是嵌套栈的
navigation对象,goBack()也就只会在嵌套栈内触发返回操作
补充:你的HOC写法的潜在问题
标准的React高阶组件应该把Hook逻辑放在返回的组件内部,避免在HOC外层调用Hook导致的上下文错误。修正后的HOC写法如下:
export const withBack = (WrappedComponent) => { // 将Hook移到返回的组件内部 return (props) => { const { colors } = useTheme(); const navigation = useNavigation(); return <> <SafeAreaView style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 1, }}> <Appbar.Header style={{ backgroundColor: colors.onSurface, position: 'absolute', backgroundColor: 'transparent' }}> <Appbar.BackAction onPress={() => navigation.goBack()} color='black'/> </Appbar.Header> </SafeAreaView> <SafeAreaView style={{ flex: 1, backgroundColor: colors.onSurface}}> <WrappedComponent {...props} /> </SafeAreaView> </>; } }
修改后,直接用component={withBack(Branches)}就能正常实现嵌套栈内返回,因为useNavigation会在屏幕渲染时才调用,此时上下文是嵌套栈的导航层级。
内容的提问来源于stack exchange,提问作者Qrow Saki
相关产品推荐
相关产品推荐

