N
Nuxt6mo ago
Yann

Beginner question - Hydration problem on computed property

Hello everyone, i'm new to Nuxt 3, had a good knowledge of Vue 3, but i'm facing an error which drive me crazy. I've an computed data which came from an Pinia getters, and, based on this data, i'm trying to make a dynamic button link and text. And i have two Hydration problem... Here's some code : layouts/default.vue
<v-btn
class="ml-1 primary--gradient text-body-2"
color="primary"
height="48"
rounded="lg"
:text="authenticated ? $t('navigation.frontend.dashboard') : $t('navigation.frontend.get_started')"
:to="authenticated ? '/dashboard' : '/auth/login'"
variant="outlined"
/>
<v-btn
class="ml-1 primary--gradient text-body-2"
color="primary"
height="48"
rounded="lg"
:text="authenticated ? $t('navigation.frontend.dashboard') : $t('navigation.frontend.get_started')"
:to="authenticated ? '/dashboard' : '/auth/login'"
variant="outlined"
/>
computed: {
authenticated(): boolean {
return useAuthStore().authenticated
}
}
computed: {
authenticated(): boolean {
return useAuthStore().authenticated
}
}
stores/auth.ts
state: (): Auth => ({
access_token: null
}),

getters: {
authenticated(state): boolean {
return !!state.access_token
}
},

// [...]
persist: {
paths: ['access_token'],
afterRestore: (context: PiniaPluginContext): void => {
const { $http } = useNuxtApp()
const { access_token } = context.store.$state as Auth
$http.defaults.headers.Authorization = `Bearer ${access_token}`
}
}
state: (): Auth => ({
access_token: null
}),

getters: {
authenticated(state): boolean {
return !!state.access_token
}
},

// [...]
persist: {
paths: ['access_token'],
afterRestore: (context: PiniaPluginContext): void => {
const { $http } = useNuxtApp()
const { access_token } = context.store.$state as Auth
$http.defaults.headers.Authorization = `Bearer ${access_token}`
}
}
I'm using axios instead of useFetch because i've some habits with it and i didn't see how can i put some default parameters on $fetch (like baseURL or headers). That may be my problem ?? So, if any good soul can help me...
20 Replies
ʏᴜᴢᴢᴜᴡᴏ
useFetch provides baseURL etc what is the exact hydration problem?
Yann
YannOP6mo ago
The problem is "Server rendered /auth/login" "Client expected : /dashboard" Because I'm logged in The "authenticated" value is true when I'm connected if you look at the ternary operator on the layout Where did you see that ? Maybe I've miss this part, if yes, I'll use this instead of axios...
ʏᴜᴢᴢᴜᴡᴏ
const config = useRuntimeConfig()

//...

const { data: years, pending } = await useLazyFetch<APIResponseArray<Year>>("/years/import", {
baseURL: config.public.baseURL,
pick: ["data"],
})
const config = useRuntimeConfig()

//...

const { data: years, pending } = await useLazyFetch<APIResponseArray<Year>>("/years/import", {
baseURL: config.public.baseURL,
pick: ["data"],
})
from my own code nuxt config:
runtimeConfig: {
public: {
baseURL: process.env.BACKEND_API,
},
},
runtimeConfig: {
public: {
baseURL: process.env.BACKEND_API,
},
},
I have seperate backend that is why i use it Try wrap it in <ClientOnly> component
Yann
YannOP6mo ago
My app will be a whole dashboard with authentication required without any need of SSR, only a few landing page should be referenced and will use SEO... So I'm wondering if Nuxt is adapted to my project
ʏᴜᴢᴢᴜᴡᴏ
you can define routeRules in nuxt config,
Yann
YannOP6mo ago
Or I can just put the dashboard layout inside a <ClientOnly/> component ? Oh great
ʏᴜᴢᴢᴜᴡᴏ
with route rule you can make the whole page ssr: false
Yann
YannOP6mo ago
Does this impact any library like Vuetify ? Which need to know if SSR is enabled or not
ʏᴜᴢᴢᴜᴡᴏ
I dont think so
Yann
YannOP6mo ago
If you want, here's my codebase : https://github.com/vitadocs/web-frontend
GitHub
GitHub - vitadocs/web-frontend
Contribute to vitadocs/web-frontend development by creating an account on GitHub.
Yann
YannOP6mo ago
Okay, so my use case is like the "admin dashboard" Except for the button which need to be wrapped inside a <ClientOnly/> block Thank you, you really helped me ! But, just to know, I'm doing something wrong, or that's the "normal" way to read the computed data (with the <ClientOnly/>)
ʏᴜᴢᴢᴜᴡᴏ
With SSR, your code runs both on server and client with ClientOnly, it only runs on client
Yann
YannOP6mo ago
Understood 😅
ʏᴜᴢᴢᴜᴡᴏ
for example dark/light mode is based on user, server doesnt know it, so there will be hydration issue. That is why you should put dark/light toggle switch in ClientOnly just for example
Yann
YannOP6mo ago
Just like the button text for example, server doesn't care about it, just render the button not logged in So, there'll be no button at all for rendered page or can I put a default button ? Like a v-if ?
ʏᴜᴢᴢᴜᴡᴏ
yes, then it runs again on client, but he is logged in, so vue has to render it different. then there is mismatch
Yann
YannOP6mo ago
Okay, so, thank you for all the tips 😉 I'll update the code, thank you !
Dubem
Dubem6mo ago
If you want a seamless feel for an autheticated user, you can store their data on localstorage, maybe use pinia-persist plugin. Then clear it when their token is expired or on loggout.
Want results from more Discord servers?
Add your server