【问题标题】:How to write redirection inside the axios interceptors without reloading in React JS如何在 axios 拦截器中编写重定向而不在 React JS 中重新加载
【发布时间】:2019-11-19 00:21:22
【问题描述】:

我使用 axios 拦截器来维护内部服务器错误。如果响应有错误而不重新加载,我需要重定向到另一个 url。下面的代码我使用了 location.href。所以它正在重新加载。我需要一个解决方案来重定向而不刷新页面。

我在 react-router-dom 中尝试了“重定向”。但这对我不起作用。

export function getAxiosInstance() {
    const instance = axios.create();
    const token    = getJwtToken();

    // Set the request authentication header
    instance.defaults.headers.common['Authorization'] = `Bearer ${token}`;

    // Set intercepters for response
    instance.interceptors.response.use(
        (response) => response,
        (error) => {
            if (config.statusCode.errorCodes.includes(error.response.status)) {
                return window.location.href = '/internal-server-error';
            }

            return window.location.href = '/login';
        }
    );

    return instance;
}

谁能帮我解决这个问题?

【问题讨论】:

  • 你在使用 Redux 吗?
  • @MosèRaguzzini 是的,我是。
  • 好的,您可以导入您的商店实例并调度在这种情况下将更改路线的操作。或者您可以在我的回答中采用以下解决方案。
  • @MosèRaguzzini 谢谢。我会试试你的解决方案。

标签: reactjs react-router axios interceptor


【解决方案1】:

这将利用导入缓存

// history.js
import { createBrowserHistory } from 'history'

export default createBrowserHistory({
  /* pass a configuration object here if needed */
})


// index.js (example)
import { Router } from 'react-router-dom'
import history from './history'
import App from './App'

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder)


// interceptor.js
import axios from 'axios';
import cookie from 'cookie-machine';
import history from '../history';

axios.interceptors.response.use(null, function(err) {
  if ( err.status === 401 ) {
    cookie.remove('my-token-key');
    history.push('/login');
  }

  return Promise.reject(err);
});

【讨论】:

  • 我使用了历史库。它对我不起作用。只更改了浏览器网址。不重定向。
  • 你必须导出 browserHistory 的实例,而不是 browserHistory 本身
  • 我在你的回答中做了同样的事情。我使用的是 react-router-dom 中的 'BrowserRouter' 而不是“Router”。 “导出 browserHistory 的实例,而不是 browserHistory 本身”是什么意思。
  • 看一下我的history.js文件,如果它为app和axios抽象都是这样导出的,它们引用同一个历史对象
  • 我在没有 redux 的时候使用这个方法,而使用 redux 我只是调度一个作用于同一个历史对象的动作
【解决方案2】:

我通过将 useHistory()&lt;Router&gt; 内部传递给 axios 拦截器解决了这个问题。

App.js:

// app.js

function App() {
  return (
    <Router>
      <InjectAxiosInterceptors />

      <Route ... />
      <Route ... />
    </Router>
  )
}

InjectAxiosInterceptors.js:

import { useEffect } from "react"
import { useHistory } from "react-router-dom"
import { setupInterceptors } from "./plugins/http"

function InjectAxiosInterceptors () {
  const history = useHistory()

  useEffect(() => {
    console.log('this effect is called once')
    setupInterceptors(history)
  }, [history])

  // not rendering anything
  return null
}

插件/http.js:

import axios from "axios";

const http = axios.create({
  baseURL: 'https://url'
})

/**
 * @param {import('history').History} history - from useHistory() hook
 */
export const setupInterceptors = history => {
  http.interceptors.response.use(res => {
    // success
    return res
  }, err => {
    const { status } = err.response
  
    if (status === 401) {
      // here we have access of the useHistory() from current Router
      history.push('/login')
    }
  
    return Promise.reject(err)
  })
}

export default http

【讨论】:

    【解决方案3】:

    您应该使用历史对象来推送新位置。检查这个问题How to push to History in React Router v4?。这应该会有所帮助。

    【讨论】:

    • 我使用了历史库。它对我不起作用。只更改了浏览器网址。不会发生重定向。
    猜你喜欢
    • 2021-12-25
    • 2022-01-09
    • 2018-12-25
    • 2017-04-08
    • 2017-08-29
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多