DEV Community

Discussion on: React hooks in Axios interceptors

Collapse
 
devadossedison profile image
Edison Devadoss • Edited
import axios, {
  AxiosError,
  AxiosRequestConfig,
  AxiosRequestHeaders,
  AxiosResponse
} from 'axios';
import environment from '../config/environment';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';

import { useSelector, useDispatch } from 'react-redux';
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

const toastId: string = 'interceptor';

interface ErrorData {
  errors: string[];
}

const http = axios.create({
  baseURL: environment.baseURL
});

const parseErrorMessage = (errResponse: AxiosResponse<ErrorData>): string => {
  console.log('errResoponse', errResponse);
  return errResponse?.data ? errResponse.data?.errors[0] : '';
};

const AxiosInstance = ({ children }: any) => {
  const navigate = useNavigate();
  const [isSet, setIsSet] = useState(false);
  const token = useSelector((state: any) => state.auth.token);

  useEffect(() => {
    // needs to fix
    const reqInterceptor = (config: any) => {
      if (token) {
        if (config.headers) {
          config.headers['Authorization'] = `Bearer ${token}`;
        }
      }
      return config;
    };

    const resInterceptor = (response: AxiosResponse) => {
      return response.data;
    };

    const errInterceptor = (error: AxiosError) => {
      const message = parseErrorMessage(
        error.response as AxiosResponse<ErrorData>
      );
      if (message) {
        error.message = message;
      }
      const currentPath = window.location.pathname;
      if (error.response?.status === 401 && !currentPath.includes('login')) {
        console.log('in side', currentPath.includes('login'));
        if (!toast.isActive(toastId)) {
          toast.error(message, { toastId });
        }
        setTimeout(() => {
          // Clear token form db
          navigate('/login');
        }, 3000);
      }
      return Promise.reject(error);
    };

    const interceptorReq = http.interceptors.request.use(
      reqInterceptor,
      (error) => {
        console.log('interceptor req error', error);
      }
    );

    const interceptorRes = http.interceptors.response.use(
      resInterceptor,
      errInterceptor
    );

    setIsSet(true);
    return () => {
      http.interceptors.request.eject(interceptorReq);
      http.interceptors.response.eject(interceptorRes);
    };
  }, [isSet, navigate, token]);
  return isSet && children;
};

export default http;
export { AxiosInstance };

Enter fullscreen mode Exit fullscreen mode

This is my code. In the request interceptor is not call all the time. After login, useEffect of the next screen it makes an API call in that call it should set header from redux. But it is not working. Where is the mistake I make?