React项目中如何在API公共封装文件实现响应码900自动跳转登录页
React项目axios统一处理900响应码的解决方案
下面提供两种可直接落地的实现方案:
方案1:直接导出history和store实例供公共文件调用
无需依赖hook,直接在非组件文件中调用路由和状态管理能力,实现成本最低:
第一步:导出路由实例
如果使用react-router v5,单独封装history文件:// src/history.ts import { createBrowserHistory } from 'history' export const history = createBrowserHistory()入口文件中替换
BrowserRouter为普通Router并传入上面导出的history即可。如果使用react-router v6,直接导出创建的router实例:
// src/router.ts import { createBrowserRouter } from 'react-router-dom' export const router = createBrowserRouter([ { path: '/login', element: <LoginPage /> }, // 剩余原有路由配置... ])第二步:导出全局store实例
在你创建redux store的文件中直接导出实例:// src/store.ts import { configureStore } from '@reduxjs/toolkit' import userReducer from './slices/userSlice' export const store = configureStore({ reducer: { user: userReducer, // 其他reducer配置 } })第三步:修改
handleResponse统一处理900逻辑// response.ts // v5引入history import { history } from '../history' // v6引入router // import { router } from '../router' import { store } from '../store' import { logoutUser } from './slices/userSlice' export function handleResponse(response: any) { const res = response.data ?? response // 统一拦截900状态码 if (res.code === 900) { store.dispatch(logoutUser()) // v5跳转 history.push('/login') // v6跳转 // router.navigate('/login') // 抛出错误中断后续业务逻辑,避免业务侧重复判断 throw new Error('登录已过期,请重新登录') } // 原有返回逻辑保留 if (res.results) { return res.results; } if (res.data) { return res.data; } return res; }
修改完成后业务侧可以直接删除所有900状态码的判断逻辑,无需额外处理。
方案2:事件订阅实现解耦
如果不想让公共文件依赖路由和状态库,或者方案1出现循环导入问题,可以用事件订阅的方式实现:
- 第一步:封装轻量事件总线
// src/utils/eventBus.ts type EventHandler = (...args: any[]) => void const eventMap = new Map<string, EventHandler[]>() export const eventBus = { on: (event: string, handler: EventHandler) => { if (!eventMap.has(event)) eventMap.set(event, []) eventMap.get(event)!.push(handler) }, emit: (event: string, ...args: any[]) => { eventMap.get(event)?.forEach(handler => handler(...args)) }, off: (event: string) => { eventMap.delete(event) } } - 第二步:公共层拦截900时抛出事件
// response.ts import { eventBus } from '../utils/eventBus' export function handleResponse(response: any) { const res = response.data ?? response if (res.code === 900) { eventBus.emit('auth_expired') throw new Error('登录已过期,请重新登录') } // 原有返回逻辑保留 if (res.results) { return res.results; } if (res.data) { return res.data; } return res; } - 第三步:根组件监听事件处理逻辑
在应用根组件中用hook监听事件,执行登出和跳转:// App.tsx import { useEffect } from 'react' import { useDispatch } from 'react-redux' // v5用useHistory import { useHistory } from 'react-router-dom' // v6用useNavigate // import { useNavigate } from 'react-router-dom' import { logoutUser } from './slices/userSlice' import { eventBus } from './utils/eventBus' function App() { const dispatch = useDispatch() const history = useHistory() // const navigate = useNavigate() useEffect(() => { const handleAuthExpired = () => { dispatch(logoutUser()) history.push('/login') // navigate('/login') } eventBus.on('auth_expired', handleAuthExpired) return () => eventBus.off('auth_expired') }, [dispatch, history]) // 原有App组件逻辑保留 }
提示:如果900状态码是在HTTP错误响应中返回(比如HTTP状态码为401),需要在
handleError函数中同步添加相同的判断逻辑。
内容的提问来源于stack exchange,提问作者Jin Park
相关产品推荐
相关产品推荐

