Search code examples
nuxt3.jsnuxt-link

Nuxt3: Hydration class mismatch on ssr when loading NuxtLinks asynchronously


In a header component I want to load the links asynchronously. I was wondering why on the initial (server rendered) page the NuxtLinks had no active class, so I found this error message in the console when accessing localhost:3000/blog

[Vue warn]: Hydration class mismatch on <a href=​"/​blog" class data-v-49fb23b8>​Blog​</a>​ 
  - rendered on server: class=""
  - expected on client: class="router-link-active router-link-exact-active"
  Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead.
  You should fix the source of the mismatch. 
  at <RouterLink ref=fn to="blog" activeClass=undefined  ... > 
  at <NuxtLink to="blog" > 
  at <Header> 
  at <Default ref=Ref< undefined > > 
  at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
  at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
  at <NuxtLayout> 
  at <App key=4 > 
  at <NuxtRoot>

This is how the <Header> component looks like:

I am using a setTimeout to mimic the async call I want to make.

<template>
    <ul>
      <li v-for="link in links" :key="link.id">
        <NuxtLink :to="link.slug" >
          {{ link.name }}
        </NuxtLink>
      </li>
    </ul>
</template>

<script setup>
  const {data: links} = await useAsyncData(() => {
    return new Promise((resolve, reject) => {
      setTimeout(
        () => resolve(
          [
            { id: 1, slug: 'blog', name: 'Blog' }, 
            { id: 2, slug: 'about', name: 'About' }
          ]
      ), 500)
    });
  });
</script>

<style scoped> 
.router-link-active {
  color: red;
}
</style>

From what I've read the async call should already be awaited on the server side and thus the active class should be set already on the server (from https://nuxt.com/docs/getting-started/data-fetching#suspense).

From the error messages it looks like the active class is missing on the server rendered part?

I am not sure what I am doing wrong, I'm still a bit unaccustomed with Nuxt3 and Vue.

I could maybe try to use a custom fetch (https://nuxt.com/docs/guide/recipes/custom-usefetch) but I 'm not sure why it should not also work with useAsyncData()


Solution

  • With the help of Reagan's comment I found out it had to do something in my page.

    It was a bit tricky now to reproduce since the error occured only when freshly starting the Nuxt dev server and then refreshing.

    What fixed it for me was now using a ref() where I actually needed one. That seemed to cause the conflict somehow.