如何在 axios 拦截器中编写重定向而不在 React JS 中重新加载
Posted
技术标签:
【中文标题】如何在 axios 拦截器中编写重定向而不在 React JS 中重新加载【英文标题】:How to write redirection inside the axios interceptors without reloading in 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 谢谢。我会试试你的解决方案。 【参考方案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()
从 <Router>
内部传递给 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?。这应该会有所帮助。
【讨论】:
我使用了历史库。它对我不起作用。只更改了浏览器网址。不会发生重定向。以上是关于如何在 axios 拦截器中编写重定向而不在 React JS 中重新加载的主要内容,如果未能解决你的问题,请参考以下文章
React 路由器 + Axios 拦截器。如何进行重定向?
如何使用 React Router V4 从 axios 拦截器重定向?