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

React共享服务中使用useNavigate触发无效Hook调用的解决方法

解决React Router useNavigate在共享服务中的使用问题

你遇到的错误核心原因是违反了React Hooks规则:useNavigate作为Hook,只能在函数组件的顶层或者自定义Hook的顶层调用,而你直接在普通函数Redirect中调用它,当通过COMMON.redirect('/')执行时,这个调用不在React组件的渲染上下文里,所以触发了Invalid hook call错误。

下面是两种可行的解决方案,都能实现无需重复导入useNavigate的需求:

方案一:自定义Hook(推荐)

创建一个自定义Hook,在内部封装useNavigate并导出redirect方法,这样组件调用这个Hook时,Hook的执行处于组件渲染上下文内,符合规则:

// CommonService.tsx
import { useNavigate } from "react-router-dom";

export function useCommon() {
  const navigate = useNavigate();

  // 封装redirect方法
  const redirect = (route: string) => {
    navigate(route);
  };

  // 可在此添加更多共享方法
  return {
    redirect
  };
}

在组件中使用:

// 任意组件文件
import { useCommon } from './CommonService';

function MyComponent() {
  const { redirect } = useCommon();

  const handleClick = () => {
    redirect('/'); // 正常调用
  };

  return <button onClick={handleClick}>返回首页</button>;
}

方案二:导航上下文(适配非组件场景)

如果需要在非组件(比如工具函数、异步回调)中实现导航,可以通过React Router的导航上下文来获取导航函数:

1. 创建导航上下文与Provider

// NavigationContext.tsx
import { createContext, useContext, useNavigate } from "react-router-dom";

const NavigationContext = createContext<{ redirect: (route: string) => void } | null>(null);

export function NavigationProvider({ children }: { children: React.ReactNode }) {
  const navigate = useNavigate();

  const redirect = (route: string) => {
    navigate(route);
  };

  return (
    <NavigationContext.Provider value={{ redirect }}>
      {children}
    </NavigationContext.Provider>
  );
}

export function useNavigation() {
  const context = useContext(NavigationContext);
  if (!context) {
    throw new Error('useNavigation必须在NavigationProvider内部使用');
  }
  return context;
}

2. 在路由外层包裹Provider

// App.tsx
import { BrowserRouter } from "react-router-dom";
import { NavigationProvider } from './NavigationContext';

function App() {
  return (
    <BrowserRouter>
      <NavigationProvider>
        {/* 你的路由组件 */}
      </NavigationProvider>
    </BrowserRouter>
  );
}

3. 在组件/非组件中调用

// 组件中使用
import { useNavigation } from './NavigationContext';

function MyComponent() {
  const { redirect } = useNavigation();
  // 业务逻辑中调用redirect
}

// 非组件工具函数(需在React组件树的回调中调用,不可直接在异步函数顶层执行)
async function fetchData() {
  const res = await fetch('/api/data');
  if (res.status === 401) {
    const { redirect } = useNavigation();
    redirect('/login');
  }
}

内容的提问来源于stack exchange,提问作者redrom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:00:04