For my application, I am utilizing Nuxt.js. On one of the pages, I am using AsyncData
to fetch an array of data objects from my API asynchronously. These data objects are then rendered in my template using v-for
. Everything is functioning properly until I introduce either nuxt-link
or
<a href=".."></a>
within the v-for
. When that happens, I encounter the following error:
The client-side rendered virtual DOM tree is not matching server-rendered content.
This is likely caused by incorrect HTML markup, such as nesting block-level elements inside <p>, or missing <tbody>.
Bailing hydration and performing full client-side render.
Here is a simplified example of what I'm trying to achieve:
<template>
<div>
<div
class="place-card"
:key="place._id"
v-for="place in places"
>
<nuxt-link
:to="{
name: 'places-title',
params: { title: place.title }
}"
>
<PlaceCard :place="place" />
</nuxt-link>
</div>
</div>
</template>
<script>
export default {
asyncData() {
// Some preprocessing
return { places: [{...}, ..., {...}] }
}
}
</script>
I was able to resolve this issue by wrapping the entire v-for
div with
<client-only>...</client-only>
, which is detailed in @Mohsens answer here as well as here.
However, using
<client-only></client-only>
eliminates server-side rendering of the async data, which is essential for SEO purposes.
Does anyone have another solution to address this problem?
EDIT 12.10.2020 Extended log
Here is the original code for the PlaceCard
component:
<template>
<div class="bg-white rounded overflow-hidden shadow-lg">
<img :src="place.images[0]" :alt="place.title" class="w-full h-40" />
<div class="px-6 pt-4">
<div class="font-bold text-base">{{ place.title }}</div>
</div>
<div class="px-6 pb-4">
<nuxt-link :to="'/'"
>#{{ place.placeType.split(' ').join('') }}</nuxt-link
>
<nuxt-link :to="'/'">#{{ place.address.country }}</nuxt-link>
<nuxt-link :to="'/'" v-if="place.vegan">#vegan</nuxt-link>
<nuxt-link :to="'/'" v-else>#not-vegan</nuxt-link>
<nuxt-link :to="'/'" v-if="place.vegetarian">#vegetarian</nuxt-link>
<nuxt-link :to="'/'" v-else>#not-vegetarian</nuxt-link>
</div>
<div class="author flex items-center py-3 px-6">
<div class="user-logo">
<img
class="w-8 h-8 object-cover rounded-full mr-2 shadow"
:src="place.creator.photoURL"
:alt="place.creator.displayName"
/>
</div>
<div class="block text-xs">
Added by<a href="#" class="ml-1">{{
place.creator.displayName.split(' ').join('')
}}</a>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
place: {
type: Object,
default: null
}
}
}
</script>