claud.io
claud.io

Reputation: 1953

vue3 performance warning using ref

vue is throwing this message:

Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw or using shallowRef instead of ref.

<template>
      <component v-for="(el, idx) in elements" :key="idx" :data="el" :is="el.component" />
</template>



 setup() {
    const { getters } = useStore()
    const elements = ref([])
    onMounted(() => {
      fetchData().then((response) => {
        elements.value = parseData(response)
      })
    })
    return { parseData }
}

is there a better way to do this?

Upvotes: 31

Views: 40526

Answers (6)

Benjamin Fourgeaud
Benjamin Fourgeaud

Reputation: 864

First, you should return { elements } instead of parseData in your setup, I think.


I solved this issue by marking the objects as shallowRef:

import { shallowRef,  ref, computed } from 'vue'
import { EditProfileForm, EditLocationForm, EditPasswordForm} from '@/components/profile/forms'

const profile = shallowRef(EditProfileForm)
const location = shallowRef(EditLocationForm)
const password = shallowRef(EditPasswordForm)

const forms = [profile, location, password] 
<component v-for="(form, i) in forms" :key="i" :is="form" />

So you should shallowRef your components inside your parseData function. I tried markRaw at start, but it made the component non-reactive. Here it works perfectly.

Upvotes: 33

Caffeine Cat
Caffeine Cat

Reputation: 79

I also meet this problem today,and here is my solution to solve it:

setup() {
  const routineLayoutOption = reactive({
    board: {
      component: () => RoutineBoard,
    },
    table: {
      component: () => RoutineTable,
    },
    flow: {
      component: () => RoutineFlow,
    },
  });
}
I set the component variant as the result of the function. And in the ,bind it like compoennt()

    <component
        :is="routineLayoutOption[currentLayout].component()"
      ></component>

Upvotes: 1

JoshX
JoshX

Reputation: 49

I had this warning while displaying an SVG component; from what I deduced, Vue was showing the warning because it assumes the component is reactive and in some cases the reactive object can be huge causing performance issues.

The markRaw API tells Vue not to bother about reactivity on the component, like so - markRaw(<Your-Component> or regular object)

Upvotes: 1

Jaredcheeda
Jaredcheeda

Reputation: 2004

For me, I had defined a map in the data section.

<script>
import TheFoo from '@/TheFoo.vue';

export default {
  name: 'MyComponent',
  data: function () {
    return {
      someMap: {
        key: TheFoo
      }
    };
  }
};
</script>

The data section can be updated reactively, so I got the console errors. Moving the map to a computed fixed it.

<script>
import TheFoo from '@/TheFoo.vue';

export default {
  name: 'MyComponent',
  computed: {
    someMap: function () {
      return {
        key: TheFoo
      };
    }
  }
};
</script>

Upvotes: 2

tastytim
tastytim

Reputation: 331

I had the same error. I solved it with markRaw. You can read about it here!

my code :

import { markRaw } from "vue";
import Component from "./components/Component.vue";
data() {
    return {
      Component: markRaw(Component),
}

Upvotes: 14

ali emili
ali emili

Reputation: 806

you could manually shallowCopy the result

<component v-for="(el, idx) in elements" :key="idx" :data="el" :is="{...el.component}" />

Upvotes: 29

Related Questions