Skip to content
Advertisement

Axios instance not getting the token from local storage on first call – React js + django

I created an Axios instance to set up the baseURL and the headers. The header also needs to contain the token for authorization. So when a user logs in I call an API to fetch some data related to the user using useEffect. So the API gets called immediately after the login is completed. This API needs permissions and hence requires the token. On login, I store the token in local storage but for some reason, the token is not loaded on the first call of the instance and I get an Unauthorised error from the backend. But then if I manually reload the page, the API gets called again but this time the token is received by the instance and the data is fetched. Below is my code.

axios instance

const baseURL = "http://127.0.0.1:8000";

// getting the token from the localstorage
let authTokens = localStorage.getItem("token")
  ? JSON.parse(localStorage.getItem("token"))
  : null;

const axiosInstance = axios.create({
  baseURL,
  headers: { Authorization: `Bearer ${authTokens?.access}` },
});

api call

export const fetchTeacherDetail = async () => {
 
  try {
    let response = await axiosInstance.get(`/teacher/get-detail/`);
    return response;
  } catch (error) {
    ToastNotification(
      "We are facing some errors. Please trying again later.",
      "error"
    );
  }
};

I followed a youtube video to learn this, he is not getting this error but for some reason I am getting this error. Please suggest to me what should I do.

Update

code to show where I store the token in the local storage

action that stores the token and user details in redux

export const loginUser = (email, password) => async (dispatch) => {
  try {
    // before calling the api
    dispatch(loginPending());

    //calling the api
    const response = await userLogin(email, password);
    if (response.status !== 200) {
      return dispatch(loginFail(response.status));
    } else {
      dispatch(loginSuccess(response.data));
    }
  } catch (error) {
    dispatch(loginFail(error.message));
  }
};

userLogin() API code

export const userLogin = async (email, password) => {
  const config = {
    headers: {
      "Content-Type": "application/json",
    },
  };

  const body = JSON.stringify({ email, password });

  try {
    const response = await axios.post(`${url}/token/`, body, config);
    if (response.status === 200) {
      localStorage.setItem("token", JSON.stringify(response.data));
      return response;
    }
  } catch (error) {
    ToastNotification("Credentials provided are not valid", "error");
  }
};

mocking value of the response.data received int the above function

 refresh: 'eyJ0eXAiOiJKV1QUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY1ODU4NTUxMSwiaWF0IjoxNjUwODA5NTExLCJqdGkiOiI4NDRjZWFjNTFkOWI0OGNkOWE0MTFlYzU4ZWY4ZDMxYiIsInVzZXJfaWQiOiI0YjdhODEzYmFkYi05VzZXIiOmZhbHNlLCJpc19zdGFmZiI6ZmFsc2V9.zlGb4tPtJ9HlUvSUZW6QrHHfDsUU8hZ6rliYc3RbJXQ',
access: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjU4NTg1NTExLCJpYXQiOjEk1MTEsImp0aSI6ImEyYzg1NzAyZmY0ZjQ4YmRiZjEwZjEzNTUwYjk0MzE2IiwidXNlcl9pZCI6lciI6dHJ1Zsc2UsImlzX3N1cGVydXNlciI6ZmFsc2UsImlzX3N0YWZmIjpmYWxzZX0.qrictVbES22dGpA0dpVA5KLTZkrMsCM0hDHq2Yrs

Advertisement

Answer

Your issue probably happens because you set the axios instance token on the application startup, but never update it upon login.

You would need to “refresh” the value when a login happens by checking again for the localStorage data.

A quick solution would be to calculate the headers every time you call the API

const baseURL = "http://127.0.0.1:8000";

export const getToken = () => localStorage.getItem("token")
  ? JSON.parse(localStorage.getItem("token"))
  : null;

export const getAuthorizationHeader = () => `Bearer ${getToken()}`;

export const axiosInstance = axios.create({
  baseURL,
  headers: { Authorization: getAuthorizationHeader() },
});

And then in the API call

export const fetchSomething = async () => {
  try {
    const response = await axiosInstance.get("/foo", { 
      headers: { Authorization: getAuthorizationHeader() }
    });

    return response;

  } catch (error) {
    // error handling
  }
};

Another solution would be mutating the axios instance when a login happens by doing something like this

axiosInstance.defaults.headers.Authorization = `Bearer ${result.access}`
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement