Utiliser new Date()
dans Nuxt
À un moment donné du développement de votre application JavaScript Nuxt, vous souhaiterez utiliser l'objet Date
via son constructeur new Date()
pour obtenir la date ou l'heure actuelle.
const now = new Date()
Ce faisant, vous obtiendrez une erreur de décalage d'hydratation (hydration mismatch). En effet, new Date()
est exécuté côté serveur lors de la génération de la page, puis côté client lors de l'hydratation de la page. Les deux dates étant séparées de quelques millisecondes, Nuxt détecte une différence dans leur valeur respective et retourne un avertissement de décalage d'hydratation dans la console.
<script setup>
const now = new Date()
</script>
<template>
<div>{{ now }}</div>
</template>
Solution
La solution la plus simple et efficace consiste à envelopper new Date()
dans la fonction Nuxt useState()
.
<script setup>
const now = useState(() => new Date())
console.log(now.value)
</script>
<template>
<div>{{ now }}</div>
</template>
La valeur de now
est maintenant calculée côté serveur, puis envoyée au client via la variable payload1 de Nuxt.
Pour en savoir plus : useState composable - Nuxt docs
Autres pistes
Suivant le contexte, il existe d'autres façons de gérer ou de contourner ce problème. Il faudra alors garder à l'esprit que la date retournée par new Date()
est différente côté serveur et côté client.
- En utilisant le composant Nuxt
<ClientOnly>
2
<script setup>
const now = new Date()
</script>
<template>
<ClientOnly>
<h1>{{ now }}</h1>
</ClientOnly>
</template>
- En rajoutant le suffixe
.client.vue
au fichier de la page3 ou du composant4, pour que celui-ci ne soit exécuté que côté client. - En utilisant le crochet
onMounted()
proposé par Vue.js5, qui n'est pas exécuté côté serveur.
<script setup>
const now = ref()
onMounted(() => {
now.value = new Date()
})
</script>
- Ou inversement, calculer la variable côté serveur seulement, en utilisant l'objet
import.meta.server
6 de Nuxt. ⚠now.value
seraundefined
côté client !
<script setup>
const now = ref()
if (import.meta.server) {
now.value = new Date()
}
</script>
- Depuis Vue
v3.5
, il est possible d'utiliser l'attributdata-allow-mismatch
pour effacer l'avertissment de décalage d'hydratation dans la console7.