Stack Overflow Asked by Daniel von Mirbach on December 22, 2020
I am using Nuxt.js for my application. In one of my pages I use AsyncData
to asynchronously fetch an array of data objects from my Api, which I render in my template using v-for
. This is working fine when I don’t use nuxt-link
or <a href=".."></a>
inside the v-for
. As soon as I include nuxt-link
or <a href=".."></a>
inside my v-for
, I get the following error:
The client-side rendered virtual DOM tree is not matching server-rendered content.
This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>.
Bailing hydration and performing full client-side render.
A basic example of what I try to accomplish:
<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 get it working, when I wrap the whole v-for
div into <client-only>...</client-only>
as described here in @Mohsens answer as well as here.
Unfortunately, <client-only></client-only>
prevents server-side-rendering of the async data. However, I do need pre-fetching my data on the server-side, because of SEO.
Does anyone know another solution for this problem?
EDIT 12.10.2020
Extended log
Original code of 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>
I figured it out. According to here and here, I had a nested link, the one inside my v-for
div and another inside my PlaceCard
component, which isn't allowed.
Correct answer by Daniel von Mirbach on December 22, 2020
Template should only contain 1 element thats fine. But you should not loop the top parent element. Try to wrap it in an div
<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>
Answered by Ifaruki on December 22, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP