I’m having an issue where my Pinia store will contain null
for each of its state properties if I try to access it via onMounted
hook. It’s a little more complex than that. Here is the call stack basically
- Component (OnMounted) calls
- Composable calls
- Pinia Store
Component
<code>onMounted(async () => {
const resp = await $authFetch(config.functionsBaseUrl + 'v1/account/settings',
{
method: 'GET'
}).catch(e => {
toast.show({
type: 'error',
title: 'Error',
content: e.data
});
return null;
})
if (resp === null)
return;
userSetings.value = resp;
})
</code>
<code>onMounted(async () => {
const resp = await $authFetch(config.functionsBaseUrl + 'v1/account/settings',
{
method: 'GET'
}).catch(e => {
toast.show({
type: 'error',
title: 'Error',
content: e.data
});
return null;
})
if (resp === null)
return;
userSetings.value = resp;
})
</code>
onMounted(async () => {
const resp = await $authFetch(config.functionsBaseUrl + 'v1/account/settings',
{
method: 'GET'
}).catch(e => {
toast.show({
type: 'error',
title: 'Error',
content: e.data
});
return null;
})
if (resp === null)
return;
userSetings.value = resp;
})
Composable
<code>export async function $authFetch<T>(
request: Parameters<typeof $fetch<T>>[0],
opts?: Parameters<typeof $fetch<T>>[1],
) {
const auth = useAuth(useNuxtApp().$pinia);
const shouldRefreshToken = () => {
const currentTime = Math.floor(Date.now() / 1000);
// Calculate the time difference between expiration time and current time
console.log('calculating', auth.tokenExpiration);
const timeDifference = auth.tokenExpiration - currentTime;
console.log('time diff', timeDifference);
// Check if the token is expiring within the next 5 minutes (300 seconds)
return timeDifference <= 300;
}
console.log('authFetch', auth, auth.tokenExpiration, shouldRefreshToken());
if (auth.tokenExpiration && shouldRefreshToken()) {
const url = useRuntimeConfig().public.functionsBaseUrl + 'v1/auth/refresh';
console.log('refreshing', url);
const resp = await $fetch(url, {
method: 'POST',
body: {
refreshToken: auth.refreshToken,
idToken: auth.token
},
headers: {
Authorization: `Bearer ${auth.token}`
}
}).catch(e => {
if (e.data === 'Unauthorized') {
//refresh token has expired, log the user out
auth.$reset();
const cookie = useCookie('auth');
cookie.value = null;
}
});
auth.token = resp.Token;
auth.tokenExpiration = resp.Expiration;
}
return $fetch<T>(request, {
...opts,
headers: {
Authorization: `Bearer ${auth.token}`,
...opts?.headers,
},
});
}
</code>
<code>export async function $authFetch<T>(
request: Parameters<typeof $fetch<T>>[0],
opts?: Parameters<typeof $fetch<T>>[1],
) {
const auth = useAuth(useNuxtApp().$pinia);
const shouldRefreshToken = () => {
const currentTime = Math.floor(Date.now() / 1000);
// Calculate the time difference between expiration time and current time
console.log('calculating', auth.tokenExpiration);
const timeDifference = auth.tokenExpiration - currentTime;
console.log('time diff', timeDifference);
// Check if the token is expiring within the next 5 minutes (300 seconds)
return timeDifference <= 300;
}
console.log('authFetch', auth, auth.tokenExpiration, shouldRefreshToken());
if (auth.tokenExpiration && shouldRefreshToken()) {
const url = useRuntimeConfig().public.functionsBaseUrl + 'v1/auth/refresh';
console.log('refreshing', url);
const resp = await $fetch(url, {
method: 'POST',
body: {
refreshToken: auth.refreshToken,
idToken: auth.token
},
headers: {
Authorization: `Bearer ${auth.token}`
}
}).catch(e => {
if (e.data === 'Unauthorized') {
//refresh token has expired, log the user out
auth.$reset();
const cookie = useCookie('auth');
cookie.value = null;
}
});
auth.token = resp.Token;
auth.tokenExpiration = resp.Expiration;
}
return $fetch<T>(request, {
...opts,
headers: {
Authorization: `Bearer ${auth.token}`,
...opts?.headers,
},
});
}
</code>
export async function $authFetch<T>(
request: Parameters<typeof $fetch<T>>[0],
opts?: Parameters<typeof $fetch<T>>[1],
) {
const auth = useAuth(useNuxtApp().$pinia);
const shouldRefreshToken = () => {
const currentTime = Math.floor(Date.now() / 1000);
// Calculate the time difference between expiration time and current time
console.log('calculating', auth.tokenExpiration);
const timeDifference = auth.tokenExpiration - currentTime;
console.log('time diff', timeDifference);
// Check if the token is expiring within the next 5 minutes (300 seconds)
return timeDifference <= 300;
}
console.log('authFetch', auth, auth.tokenExpiration, shouldRefreshToken());
if (auth.tokenExpiration && shouldRefreshToken()) {
const url = useRuntimeConfig().public.functionsBaseUrl + 'v1/auth/refresh';
console.log('refreshing', url);
const resp = await $fetch(url, {
method: 'POST',
body: {
refreshToken: auth.refreshToken,
idToken: auth.token
},
headers: {
Authorization: `Bearer ${auth.token}`
}
}).catch(e => {
if (e.data === 'Unauthorized') {
//refresh token has expired, log the user out
auth.$reset();
const cookie = useCookie('auth');
cookie.value = null;
}
});
auth.token = resp.Token;
auth.tokenExpiration = resp.Expiration;
}
return $fetch<T>(request, {
...opts,
headers: {
Authorization: `Bearer ${auth.token}`,
...opts?.headers,
},
});
}
Store
<code>export const useAuth = defineStore('auth', {
state: () => ({
token: null,
refreshToken: null,
email: null,
userId: null,
firstName: null,
lastName: null,
organizationId: null,
organizationName: null,
organizationIndustry: null,
tokenExpiration: null
}),
actions: {
setLoginPayload(loginResponse) {
this.token = loginResponse.Token;
this.refreshToken = loginResponse.RefreshToken;
this.email = loginResponse.Email;
this.userId = loginResponse.UserId;
this.firstName = loginResponse.FirstName;
this.lastName = loginResponse.LastName;
this.organizationId = loginResponse.OrganizationId;
this.organizationName = loginResponse.CompanyName;
this.organizationIndustry = loginResponse.Industry;
this.tokenExpiration = loginResponse.Expiration;
console.log('set token expiration', loginResponse.Expiration);
//set in localstorage
const cookie = useCookie('auth');
cookie.value = loginResponse;
}
}
})
</code>
<code>export const useAuth = defineStore('auth', {
state: () => ({
token: null,
refreshToken: null,
email: null,
userId: null,
firstName: null,
lastName: null,
organizationId: null,
organizationName: null,
organizationIndustry: null,
tokenExpiration: null
}),
actions: {
setLoginPayload(loginResponse) {
this.token = loginResponse.Token;
this.refreshToken = loginResponse.RefreshToken;
this.email = loginResponse.Email;
this.userId = loginResponse.UserId;
this.firstName = loginResponse.FirstName;
this.lastName = loginResponse.LastName;
this.organizationId = loginResponse.OrganizationId;
this.organizationName = loginResponse.CompanyName;
this.organizationIndustry = loginResponse.Industry;
this.tokenExpiration = loginResponse.Expiration;
console.log('set token expiration', loginResponse.Expiration);
//set in localstorage
const cookie = useCookie('auth');
cookie.value = loginResponse;
}
}
})
</code>
export const useAuth = defineStore('auth', {
state: () => ({
token: null,
refreshToken: null,
email: null,
userId: null,
firstName: null,
lastName: null,
organizationId: null,
organizationName: null,
organizationIndustry: null,
tokenExpiration: null
}),
actions: {
setLoginPayload(loginResponse) {
this.token = loginResponse.Token;
this.refreshToken = loginResponse.RefreshToken;
this.email = loginResponse.Email;
this.userId = loginResponse.UserId;
this.firstName = loginResponse.FirstName;
this.lastName = loginResponse.LastName;
this.organizationId = loginResponse.OrganizationId;
this.organizationName = loginResponse.CompanyName;
this.organizationIndustry = loginResponse.Industry;
this.tokenExpiration = loginResponse.Expiration;
console.log('set token expiration', loginResponse.Expiration);
//set in localstorage
const cookie = useCookie('auth');
cookie.value = loginResponse;
}
}
})
If I wrap the code inside the onMounted function in a 1 second delay, the store values are no longer empty
I can’t find anything anywhere that explains that Pinia needs some time to “be ready” or a way to await it to “be ready”
Is there anything obvious here why my store is empty when called in onMount?