You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在对象式路由中使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:15:29