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