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

Redux Toolkit fetchBaseQuery拦截器401跳转时useNavigate报错如何处理

问题根因

useNavigate是React专属Hook,仅支持在函数组件顶层、自定义Hook内部调用,你在utils.ts模块顶层直接调用useNavigate()不符合Hook调用规则,因此触发了无效Hook调用报错。

最优解决方案(React Router v6 官方推荐)

React Router v6 推出的createBrowserRouter支持直接导出路由实例,在非组件环境下直接调用实例的navigate方法实现跳转,无需额外中间层适配。

  1. 调整路由配置,导出路由实例
// router.ts 路由配置文件
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Login from './pages/Login';
import Home from './pages/Home';
// 其他页面导入

// 导出路由实例
export const router = createBrowserRouter([
  { path: '/login', element: <Login /> },
  { path: '/', element: <Home /> },
  // 其余路由配置
]);

// 入口文件使用路由实例
// main.tsx 中示例代码
// import { router } from './router';
// root.render(<RouterProvider router={router} />);
  1. 改造authInterceptor中间件,直接使用路由实例跳转
//authInterceptor.ts
import { isRejectedWithValue, Middleware } from '@reduxjs/toolkit';
import { router } from './router'; // 导入上面导出的路由实例

const authInterceptor: Middleware = () => (next) => (action) => {
  if (isRejectedWithValue(action) && action.payload.status === 401) {
    console.log('401 error');
    // 加replace: true避免用户点后退回到触发401的页面,优化体验
    router.navigate('/login', { replace: true });
  }
  return next(action);
};

export default authInterceptor;
兼容方案(仍使用BrowserRouter组件包裹的场景)

如果你的项目暂时还是用传统的<BrowserRouter>组件包裹应用的方式,可以通过全局变量存储navigate引用的方式实现非组件内跳转:

  1. 封装全局navigate工具
// navigateUtils.ts
import { NavigateFunction } from 'react-router-dom';

let globalNavigate: NavigateFunction | null = null;

export const setGlobalNavigate = (navigate: NavigateFunction) => {
  globalNavigate = navigate;
};

export const getGlobalNavigate = () => {
  if (!globalNavigate) throw new Error('请先在应用根组件初始化globalNavigate');
  return globalNavigate;
};
  1. 在根组件初始化全局navigate
// App.tsx 应用根组件
import { useNavigate } from 'react-router-dom';
import { setGlobalNavigate } from './navigateUtils';
import { useEffect } from 'react';

function App() {
  const navigate = useNavigate();
  useEffect(() => {
    setGlobalNavigate(navigate);
  }, [navigate]);

  // 其余根组件逻辑
  return <>{/* 应用内容、路由出口等 */}</>
}
  1. 改造中间件
//authInterceptor.ts
import { isRejectedWithValue, Middleware } from '@reduxjs/toolkit';
import { getGlobalNavigate } from './navigateUtils';

const authInterceptor: Middleware = () => (next) => (action) => {
  if (isRejectedWithValue(action) && action.payload.status === 401) {
    console.log('401 error');
    getGlobalNavigate()('/login', { replace: true });
  }
  return next(action);
};

export default authInterceptor;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:45:05