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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 03:06:04