0

I am getting the error:

The client-side rendered virtual DOM tree is not matching server-rendered content

I initialize a product as an empty object, then assign it some data at onBeforeMount. The product is passed down by v-bind to the child component. I have a reproduction which shows the error in the console.

Update: I made the same example but using the options API syntax instead of composition API, and the error does not show up (see link in the reproduction).

So, is there something wrong with my composition api-syntax?

Why does the error occur, and how can I assign some data to the product, and pass it down, without the error?

I'm using Nuxt-bridge (Vue 3 with composition APA and typescript)

<template>
  <div>
    <h2>New page</h2>
    <hr />
    <ChildComponent1 v-if="checkData" v-bind="product" />

    <!-- <ChildComponent1 v-bind="getExampleProd()" /> -->    //<-- test - no error

  </div>
</template>

<script setup lang="ts">
import { ProductInterface } from '~/types';

import { computed, onBeforeMount } from 'vue';

let product = ref<any>({});

onBeforeMount(() => {
  product.value = getExampleProd();
});

const getExampleProd = () => {
  const obj: ProductInterface = {
    id: 5,
    name: 'Hello prod',
    characteristics: {
      color: 'grey',
      shape: 'strange',
    },
  };
  return obj;
};
const checkData = computed(() => {
  if (isObjectAndNotEmpty(product.value)) {
    return true;
  } else {
    return false;
  }
});
const isObjectAndNotEmpty = (data: any) => {
  if (
    typeof data === 'object' &&
    data !== null &&
    Object.keys(data).length > 0
  ) {
    return true;
  }
  return false;
};

I added a "v-if" condition to check that the product is an object with data. It was only to see if the error would go away, but it didn't.

If I pass down the product data directly, there is no error , see the line:

<ChildComponent1 v-bind="getExampleProd()" />

The child component is basically:

<template>
  <div class="comp1">
    <h2>Child component!</h2>
  </div>
</template>

<script setup lang="ts">
import { ProductInterface } from '~/types';

interface IProps {
  id: number;
  name: string;
  characteristics: any;
}
const props = defineProps<IProps>();
Ken White
  • 123,280
  • 14
  • 225
  • 444
Galivan
  • 4,842
  • 9
  • 44
  • 76
  • Give a read to that one: https://stackoverflow.com/a/67978474/8816585 A lot of answers are available there. – kissu Oct 18 '22 at 07:22

1 Answers1

0

If you assign data to a property in the onBeforeMount hook , it apparently causes hydration issue.

I believe onBeforeMount is like created in Nuxt 2 except that onBeforeMount only runs on frontend whereascreated runs both on front + backend (therefore assigning data to properties in created causes no hydration issue.

The Options API example worked because it used the created hook.

The equivalent of onBeforeMount on Nuxt 2 I think would be this:

  created() {
    //  Only run on client: hydration issue
    if (process.client) {
      this.product = this.getExampleProd();
    }
  },

Here is an example of that (hydration issue with Nuxt 2).

The solution I would be to use onMounted instead:

onMounted(() => {
  product.value = getExampleProd();
})
Galivan
  • 4,842
  • 9
  • 44
  • 76