32

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?

3
  • Any particular reason why you're not simply binding the data? Commented Jan 14, 2021 at 10:15
  • i'm binding data inside the v-for Commented Jan 14, 2021 at 10:20
  • oh you mean why i'm using the composition api?, i came from react ant it looks much like what i'm used to. Am i wrong using it in my components? Commented Jan 14, 2021 at 10:28

6 Answers 6

33

you could manually shallowCopy the result

<component v-for="(el, idx) in elements" :key="idx" :data="el" :is="{...el.component}" />
Sign up to request clarification or add additional context in comments.

2 Comments

This worked for me , though it is not documented and is so simple ...
Why is this answer at the bottom of the page? It worked for me
32

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.

4 Comments

If I do this, nothing is rendered and I get the following warning Component is missing template or render function. If I dont use the shallowRef, component is rendered but i get this other warning ` Vue received a Component which was made a reactive objec`. Any ideas?
The problem seems to be inside your component. Have you got some code to share ?
I have exactly the same problem as @gumlym I am using an icon package vue-tabler-icons I import the component import { CheckboxIcon } from 'vue-tabler-icons'; and then when I render it with <component> I get the error that gumlym describes
@gmm same. Did you find a solution?
14

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),
}

Comments

2

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>

Comments

1

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)

Comments

1

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.