如何在对象式路由中使用useNavigation()实现抽屉导航打开功能?
问题:对象式路由配置中为headerRight添加抽屉导航打开操作
需求:项目采用对象形式定义路由,希望给headerRight添加打开抽屉导航的操作,但当前写法触发Hook调用错误。
现有代码
const tabRouter = { Calendar: { name: 'Calendar', component: Calendar, options: { tabBarIcon: ({ focused, color, size }) => { let iconName; iconName = focused ? 'calendar-alt' : 'calendar-alt'; // 可以返回任意自定义组件 return <Icon name={iconName} size={size} color={color} />; }, headerRight: () => ( <Button onPress={() => { let navigation = useNavigation() // 此处报错 navigation.dispatch(DrawerActions.openDrawer()) // 此处报错 }}> <Text>jojojojo</Text> </Button> ), tabBarActiveTintColor: '#fff', tabBarInactiveTintColor: 'grey', tabBarItemStyle: { backgroundColor: theme.brand_primary, } } }, } export default TabRouter;
报错信息
index.bundle?platfor…&runModule=t…:21971 Error: Invalid hook call. Hooks只能在函数组件的主体内部调用。可能原因如下: 1. React与渲染器(如React DOM)版本不匹配 2. 违反Hooks使用规则 3. 应用中存在多个React副本
可查看React官方关于无效Hook调用的调试修复建议。
解决方案
你不能在onPress的回调函数中使用useNavigation Hook,因为Hook只能在函数组件的顶层作用域调用,不能嵌套在事件回调里。有两种可行方案:
方案1:将options定义为接收navigation参数的函数
把路由配置中的options从对象改为函数,它会接收包含navigation的参数对象,这样就能直接在headerRight中使用导航实例:
const tabRouter = { Calendar: { name: 'Calendar', component: Calendar, options: ({ navigation }) => ({ // 改为函数,接收navigation tabBarIcon: ({ focused, color, size }) => { let iconName = focused ? 'calendar-alt' : 'calendar-alt'; return <Icon name={iconName} size={size} color={color} />; }, headerRight: () => ( <Button onPress={() => { navigation.dispatch(DrawerActions.openDrawer()) // 直接使用传入的navigation }}> <Text>jojojojo</Text> </Button> ), tabBarActiveTintColor: '#fff', tabBarInactiveTintColor: 'grey', tabBarItemStyle: { backgroundColor: theme.brand_primary, } }) }, } export default TabRouter;
方案2:将headerRight抽为独立函数组件
把headerRight的内容封装成一个单独的函数组件,在组件顶层使用useNavigation:
// 单独定义HeaderRight组件 const HeaderRight = () => { const navigation = useNavigation(); // 在组件顶层使用Hook return ( <Button onPress={() => { navigation.dispatch(DrawerActions.openDrawer()) }}> <Text>jojojojo</Text> </Button> ); }; // 路由配置 const tabRouter = { Calendar: { name: 'Calendar', component: Calendar, options: { tabBarIcon: ({ focused, color, size }) => { let iconName = focused ? 'calendar-alt' : 'calendar-alt'; return <Icon name={iconName} size={size} color={color} />; }, headerRight: () => <HeaderRight />, // 使用自定义组件 tabBarActiveTintColor: '#fff', tabBarInactiveTintColor: 'grey', tabBarItemStyle: { backgroundColor: theme.brand_primary, } } }, } export default TabRouter;
这两种方案都能规避Hook调用规则的问题,实现点击headerRight按钮打开抽屉导航的需求。
内容的提问来源于stack exchange,提问作者saam__dev
相关产品推荐
相关产品推荐

