如何在不重新加载 React JS 的情况下在 axios 拦截器中编写重定向
How to write redirection inside the axios interceptors without reloading in React JS
我使用 axios 拦截器来维护内部服务器错误。如果响应有错误而不重新加载,我需要重定向到另一个 url。下面的代码我使用了 location.href。所以它正在重新加载。我需要一个无需刷新页面即可重定向的解决方案。
我在 react-router-dom 中尝试了 "Redirect"。但它对我不起作用。
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;
}
谁能帮我解决这个问题?
您应该使用历史对象来推送新位置。检查这个问题 。这应该有所帮助。
这将利用导入缓存:
// 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);
});
我通过将 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
}
plugins/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
我使用 axios 拦截器来维护内部服务器错误。如果响应有错误而不重新加载,我需要重定向到另一个 url。下面的代码我使用了 location.href。所以它正在重新加载。我需要一个无需刷新页面即可重定向的解决方案。
我在 react-router-dom 中尝试了 "Redirect"。但它对我不起作用。
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;
}
谁能帮我解决这个问题?
您应该使用历史对象来推送新位置。检查这个问题
这将利用导入缓存:
// 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);
});
我通过将 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
}
plugins/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