React中如何在非组件函数内处理API 401并实现页面重定向?
解决方案
方案1:使用React Router全局导航实例
React Router v6+ 可以在路由初始化时获取navigate函数,将其全局导出供非组件文件调用:
- 在路由配置文件(如
router.js)中:
import { createBrowserRouter, RouterProvider, useNavigation } from 'react-router-dom'; // 声明全局navigate变量 let navigate; const router = createBrowserRouter([ // 你的路由配置项 ]); // 自定义Router组件,获取并赋值navigate function AppRouter() { const navigation = useNavigation(); navigate = navigation.navigate; return <RouterProvider router={router} />; } export { navigate, AppRouter };
- 在
apiCalls.js中导入使用:
import { navigate } from './router'; export async function getData() { try { const response = await fetch(url); const res = await response.json(); // 注意这里要加await,原代码遗漏了异步处理 if (res.status.code === 401) { // 清除本地存储的令牌(如果有) localStorage.removeItem('token'); navigate('/login'); } return res; } catch (err) { console.error('请求出错:', err); } }
注:需确保navigate在组件挂载后才会被赋值,若有组件初始化时就调用API,建议加非空判断。
方案2:封装统一请求拦截器
创建基础请求函数,所有API调用基于该函数,统一处理401错误,无需依赖React Router:
// apiCalls.js async function baseRequest(url, options = {}) { const response = await fetch(url, options); const res = await response.json(); if (res.status.code === 401) { localStorage.removeItem('token'); // 用原生跳转直接指向登录页 window.location.href = '/login'; throw new Error('未授权,请重新登录'); } return res; } // 基于基础函数封装具体API export async function getData() { return baseRequest(url); } export async function postData(data) { return baseRequest(url, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } }); }
这个方案简单直接,适合不需要React Router路由状态的场景。
方案3:事件总线解耦API与路由
在API层触发自定义事件,根组件监听事件并执行重定向,实现关注点分离:
- 在
apiCalls.js中触发事件:
export async function getData() { const response = await fetch(url); const res = await response.json(); if (res.status.code === 401) { localStorage.removeItem('token'); // 触发自定义未授权事件 window.dispatchEvent(new CustomEvent('unauthorized')); } return res; }
- 在根组件(如
App.js)中监听事件:
import { useNavigate, useEffect } from 'react-router-dom'; function App() { const navigate = useNavigate(); useEffect(() => { function handleUnauthorized() { navigate('/login'); } window.addEventListener('unauthorized', handleUnauthorized); // 组件卸载时移除监听 return () => window.removeEventListener('unauthorized', handleUnauthorized); }, [navigate]); return ( // 你的组件内容 ); }
内容的提问来源于stack exchange,提问作者nika
相关产品推荐
相关产品推荐

