I have a reactive object in the global space:
let cart = Vue.reactive({
order: {
itemsCount: 0
},
items: []
});
It works great. When we change this cart in any way (for example cart.order.itemsCount += 1;) other UI parts get updated automatically.
But if we set it to a new object (let's say we have received a new order object from server) then it breaks and won't work anymore:
cart = serverCart
We even tried cart = Vue.reactive(serverCart) and it still does not cause other UI parts to re-render.
It's possible that we set every property manaully:
cart.order.itemsCount = serverCart.order.ItemsCount;
cart.items[0].productTitle = serverCart.order[0].productTitle;
...
But this is idiotic of course.
How can we re-set a reactive object entirely in Vue.js 3?
Update:
You can see this codesandbox in action.
For setting new values reactive objects in vue3, you need to use Object.assign function and you should not reassign it
Here is an example:
<template>
{{ reactiveTest }}
<button @click="change">Change</button>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
let reactiveTest = reactive({
a: 1,
b: 2,
});
function change() {
const serverReactive = {
a: 3,
b: 4,
};
// reactiveTest = serverReactive; Do not do this
Object.assign(reactiveTest, serverReactive)
}
return {
reactiveTest,
change,
};
},
};
</script>
You are trying to copy by reference, try to copy by value with spread operator ... :
const { reactive } = Vue
const app = Vue.createApp({
el: "#demo",
setup() {
let cart = reactive({
order: {
itemsCount: 0
},
items: []
});
const someCart = {order: {itemsCount: 3}, items: [{id: 1, name: "aaa"}, {id: 2, name: "bbb"}, {id: 3, name: "444"}]}
cart = reactive({...someCart})
return {cart }
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
<p> {{ cart }}</p>
<label>change items count</label>
<input type="number" v-model="cart.order.itemsCount" />
</div>