Vue received a Component which was made a reactive object
Asked Answered
S

2

5

The problem I need to solve: I am writing a little vue-app based on VueJS3.

I got a lot of different sidebars and I need to prevent the case that more than one sidebar is open at the very same time.

To archive this I am following this article.

Now I got a problem:

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. (6)

This is my code:

SlideOvers.vue

<template>
    <component :is="component" :component="component" v-if="open"/>
</template>
<script>

export default {
    name: 'SlideOvers',
    computed: {
        component() {
            return this.$store.state.slideovers.sidebarComponent
        },
        open () {
            return this.$store.state.slideovers.sidebarOpen
        },
    },
}
</script>

UserSlideOver.vue

<template>
    <div>test</div>
</template>
<script>

export default {
    name: 'UserSlideOver',
    components: {},
    computed: {
        open () {
            return this.$store.state.slideovers.sidebarOpen
        },
        component () {
            return this.$store.state.slideovers.sidebarComponent
        }
    },
}
</script>

slideovers.js (vuex-store)

import * as types from '../mutation-types'

const state = {
    sidebarOpen: false,
    sidebarComponent: null
}

const getters = {
    sidebarOpen: state => state.sidebarOpen,
    sidebarComponent: state => state.sidebarComponent
}

const actions = {
    toggleSidebar ({commit, state}, component) {
        commit (types.TOGGLE_SIDEBAR)
        commit (types.SET_SIDEBAR_COMPONENT, component)
    },
    closeSidebar ({commit, state}, component) {
        commit (types.CLOSE_SIDEBAR)
        commit (types.SET_SIDEBAR_COMPONENT, component)
    }
}

const mutations = {
    [types.TOGGLE_SIDEBAR] (state) {
        state.sidebarOpen = !state.sidebarOpen
    },

    [types.CLOSE_SIDEBAR] (state) {
        state.sidebarOpen = false
    },

    [types.SET_SIDEBAR_COMPONENT] (state, component) {
        state.sidebarComponent = component
    }
}

export default {
    state,
    getters,
    actions,
    mutations
}

App.vue

<template>
    <SlideOvers/>
    <router-view ref="routerView"/>
</template>

<script>
import SlideOvers from "./SlideOvers";

export default {
    name: 'app',
    components: {SlideOvers},
};
</script>

And this is how I try to toggle one slideover:

<template>
  <router-link
      v-slot="{ href, navigate }"
      to="/">
    <a :href="href"
       @click="$store.dispatch ('toggleSidebar', userslideover)">
        Test
    </a>
  </router-link>
</template>
<script>
import {defineAsyncComponent} from "vue";

export default {
  components: {
  },
  data() {
    return {
      userslideover: defineAsyncComponent(() =>
          import('../../UserSlideOver')
      ),
    };
  },
};
</script>
Sateia answered 12/7, 2021 at 17:54 Comment(1)
Does this answer your question? vue3 performance warning using refThankyou
C
11

Following the recommendation of the warning, use markRaw on the value of usersslideover to resolve the warning:

export default {
  data() {
    return {
      userslideover: markRaw(defineAsyncComponent(() => import('../../UserSlideOver.vue') )),
    }
  }
}

demo

Characteristically answered 12/7, 2021 at 21:52 Comment(1)
For new comers, markDraw comes also from import { markRaw } from "vue";Slapdash
B
1

You can use Object.freeze to get rid of the warning. If you only use shallowRef f.e., the component will only be mounted once and is not usable in a dynamic component.

<script setup>
import InputField from "src/core/components/InputField.vue";

const inputField = Object.freeze(InputField);

const reactiveComponent = ref(undefined);

setTimeout(function() => {
  reactiveComponent.value = inputField;
}, 5000);

setTimeout(function() => {
  reactiveComponent.value = undefined;
}, 5000);

setTimeout(function() => {
  reactiveComponent.value = inputField;
}, 5000);
</script>

<template>
  <component :is="reactiveComponent" />
</template>
Bowie answered 22/3, 2022 at 20:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.