[Vuejs]-Vue doesn't fetch data from API in first render

1👍

Update 2

Having seen the code, I think the problem is here:

import axios from "axios";

axios.defaults.baseURL = import.meta.env.VITE_API_URL;

if (localStorage.getItem('user')) {
    const user = JSON.parse(localStorage.getItem('user'));
    axios.defaults.headers.common['Authorization'] = `Bearer ${user?.accessToken}`;
}

this will read the axios.defaults.headers when the helpers/axios.js file is loaded. This is why axios.get('/users'); only works on second load, or rather only when the authentication is already loaded into localStorage. A change to the user object or a local storage will not update since this code only runs once at the beginning, the change to axios.defaults.headers needs to be dynamic.

Update

if setTimeout didn’t work that could be due to a different issue. Also, if your request works a second time, but it also works if the authentication is passed directly, it seems to me that it has something to do with the authentication being handled implicitly.

I think what’s happening is that you are creating multiple instances of axios and relying on shared authentication

// create single axios instance
export const api = axios.create({
   withCredentials: true,
   baseURL: BASE_URL // optional
})

// then use
await api.post('/auth/login', {
  username: username,
  password: password
});

// and 
await api.get('/users');

This might make the axios instance remember the authentication information between calls. It may still require handling race condition if you have an app that doesn’t wait on the login request to finish.


I think this is just an issue with a race condition

POST:/login and GET:/users requests appear to be done in parallel.

onMounted( async () => {
  // this should wait until the `login` has been handled
  const response = await axios.get('/users');
  users.value = response.data;
})

I don’t see how you call login so can’t offer the the exact solution, but if you can store the login request state as a reactive variable, you can do something like

watch: {
  loginState:{
    immediate: true
    handler(value){
      if (value === LOADED) {
        const response = await axios.get('/users');
        users.value = response.data;
      }
    }
  }
})

here’s what the changes to the authStore might look like

export const STATES = {
  INIT:"INIT",
  PROCESSING:"PROCESSING",
  ERROR:"ERROR",
  LOADED:"LOADED",
}
export const loginState = ref(STATES.INIT);

async login (username, password) {
    loginState.value = STATES.PROCESSING
    try{
      const response = await axios.post('/auth/login', {
        username: username,
        password: password
      });
      loginState.value = STATES.LOADED
      this.user = response.data;
      localStorage.setItem('user', JSON.stringify(this.user));

      await router.push('/');
    }catch(e){
      // handle error
      loginState.value = STATES.ERROR
    }
},
👤Daniel

Leave a comment