NativeBase ActionSheet中navigation.navigate点击失效报错
你遇到的TypeError: undefined is not an object (evaluating 'navigation.navigate')报错和ActionSheet的点击事件逻辑无关。你提到其他普通组件绑定同一段跳转代码可以正常运行,说明项目的导航基础配置没有问题,核心诱因是NativeBase的Actionsheet组件默认通过Portal机制渲染到整个应用组件树的最外层,脱离了React Navigation提供的NavigationContext上下文范围,组件内部无法正常获取navigation实例,最终抛出undefined错误。
方案1:禁用ActionSheet的Portal渲染(改动最小,优先用)
给Actionsheet组件添加useRNModal属性,让组件改用React Native原生Modal渲染,不再通过Portal脱离当前组件树,就能直接继承当前页面的导航上下文:
{/* 新增useRNModal属性 */} <Actionsheet isOpen={isOpen} onClose={onClose} size="full" useRNModal> <Actionsheet.Content> <Actionsheet.Item onPress={() => { onClose(); // 先关闭弹窗再跳转,避免弹窗残留 navigation.navigate('Drawer') }} startIcon={<Icon as={<MaterialIcons name="share" />} color="muted.500" mr={3} />} > Test 1 </Actionsheet.Item> <Actionsheet.Item startIcon={<Icon as={<MaterialCommunityIcons name="link" />} color="muted.500" mr={3} />}> Test 2 </Actionsheet.Item> <Actionsheet.Item startIcon={<Icon as={<MaterialIcons name="edit" />} color="muted.500" mr={3} />}> Test 3 </Actionsheet.Item> <Actionsheet.Item startIcon={<Icon as={<MaterialIcons name="delete" />} color="muted.500" mr={3} />}> Test 4 </Actionsheet.Item> </Actionsheet.Content> </Actionsheet>
方案2:在页面顶层获取navigation实例,通过闭包访问
如果不想修改ActionSheet的默认渲染逻辑,就确保你是在MyCurrentScreen组件的顶层作用域调用useNavigation钩子拿到navigation实例,不要在Actionsheet的内部子组件里单独调用钩子(子组件被Portal传送后脱离上下文,调用钩子会返回undefined)。
页面顶层代码示例:
import { useNavigation } from '@react-navigation/native'; // MyCurrentScreen组件内部顶层 const navigation = useNavigation(); const { isOpen, onOpen, onClose } = useDisclose(); const handleJumpToDrawer = () => { onClose(); navigation.navigate('Drawer'); }
之后直接把处理函数绑定给Actionsheet.Item的onPress即可,闭包会正常持有顶层navigation的引用,不会出现找不到的问题:
<Actionsheet.Item onPress={handleJumpToDrawer} startIcon={<Icon as={<MaterialIcons name="share" />} color="muted.500" mr={3} />} > Test 1 </Actionsheet.Item>
方案3:检查根组件Provider嵌套顺序(兜底排查)
如果上述两个方案都不生效,检查项目根组件的Provider嵌套顺序,必须保证NavigationContainer包裹在NativeBaseProvider外层,不要反过来嵌套,否则全应用都可能出现导航上下文丢失的问题。正确写法参考:
import { NavigationContainer } from '@react-navigation/native'; export default () => { return ( <NavigationContainer> <NativeBaseProvider> <MyCurrentScreen /> </NativeBaseProvider> </NavigationContainer> ); };
注意:不要把
NavigationContainer写在MyCurrentScreen等子组件内部,否则会导致上下文作用域异常。
内容的提问来源于stack exchange,提问作者Muhammd Abdullah

