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

为何浏览器未跳转到/login页面?React Router 6.4.2拦截器问题

问题解决:统一处理Axios 401未授权跳转(React Router v6.4.2)

首先说你当前代码里的两个问题:

  • 拦截器里用redirect("/login")完全无效,redirect是React Router专门给loader/action函数设计的返回值,在Axios拦截器这种普通异步函数里返回它根本触发不了页面跳转。
  • 每次调用fetch函数都会新增一个Axios响应拦截器,多次调用后会堆一堆拦截器实例,导致逻辑重复执行。

你完全不需要在每个组件里单独检查响应状态,用下面两种方案就能统一处理401跳转:

方案1:全局保存navigate实例

这种方法能让你在React组件外直接调用导航方法,不用每个组件单独处理。

  1. 新建一个全局导航管理文件(比如src/utils/navigate.js):
let navigateInstance;

export const setNavigate = (navigate) => {
  navigateInstance = navigate;
};

export const getNavigate = () => navigateInstance;
  1. 在根组件里初始化全局navigate:
import { useEffect } from 'react';
import { useNavigate, Outlet } from 'react-router-dom';
import { setNavigate } from './utils/navigate';

function Root() {
  const navigate = useNavigate();

  useEffect(() => {
    setNavigate(navigate);
  }, [navigate]);

  return <Outlet />;
}
  1. 修改你的Axios请求函数,统一处理401:
    把拦截器移到函数外面,只注册一次,同时用全局navigate实例跳转:
import axios from "axios";
import { getNavigate } from "./utils/navigate";

// 只注册一次响应拦截器,避免重复执行
axios.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      console.log("Unauthorized");
      // 记得清除本地的token等认证信息
      localStorage.removeItem('authToken');
      // 调用全局navigate跳转登录页
      getNavigate()('/login');
    }
    return Promise.reject(error);
  }
);

const fetch = async (data, method, url, responseType, header) => {
  const requestObj = { method, url };
  
  if (method.toLowerCase() === "get") {
    requestObj.params = data;
  } else {
    requestObj.data = data;
  }
  
  if (responseType) {
    requestObj.responseType = responseType;
  }
  
  if (header) {
    requestObj.headers = header;
  }
  
  const result = await axios(requestObj);
  return result;
}

export default fetch;

方案2:用自定义事件总线

要是不想暴露全局navigate实例,就用自定义事件触发导航逻辑。

  1. 修改Axios拦截器,触发自定义事件:
axios.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      console.log("Unauthorized");
      localStorage.removeItem('authToken');
      // 触发自定义的未授权事件
      window.dispatchEvent(new CustomEvent('unauthorized'));
    }
    return Promise.reject(error);
  }
);
  1. 在根组件里监听事件并处理导航:
import { useEffect } from 'react';
import { useNavigate, Outlet } from 'react-router-dom';

function Root() {
  const navigate = useNavigate();

  useEffect(() => {
    const handleUnauthorized = () => {
      navigate('/login');
    };
    
    window.addEventListener('unauthorized', handleUnauthorized);
    
    // 组件卸载时记得移除监听,避免内存泄漏
    return () => {
      window.removeEventListener('unauthorized', handleUnauthorized);
    };
  }, [navigate]);

  return <Outlet />;
}

总结

不管用哪种方案,都能在Axios拦截器里统一处理401跳转,不用每个组件都写一遍检查逻辑,同时还能解决拦截器重复注册的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:00:11