8

I used axios interceptors to maintain the internal server errors. I need to redirect to another url if the response have an error without reloading. Below code I used location.href. So it's reloading. I need a solution to redirect without refreshing the page.

I tried "Redirect" in react-router-dom. But it not works for me.

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;
}

Can anyone help me to solve this out?

Hemantha Dhanushka
  • 153
  • 1
  • 5
  • 14

3 Answers3

6

This will take advantage of import caching:

// 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);
});
Mosè Raguzzini
  • 15,399
  • 1
  • 31
  • 43
2

I solved this by passing useHistory() from inside a <Router> to axios interceptors.

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
Nurul Huda
  • 1,438
  • 14
  • 12
-1

You should use a history object to push new location. Check this question How to push to History in React Router v4?. This should help.

Mykola Prymak
  • 447
  • 3
  • 5