2

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.

2
  • What if you do cart = {...serverCart} ? Commented Apr 15, 2022 at 7:03
  • @digitalniweb, did not work
    – Ali EXE
    Commented Apr 15, 2022 at 7:23

2 Answers 2

6

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>
4
  • Does not work. Please see my codesandbox.
    – Ali EXE
    Commented Apr 15, 2022 at 7:41
  • Change line 59 to this: //cart = { ...newCart }; Object.assign(cart, newCart); Codesandbox Commented Apr 15, 2022 at 7:45
  • Yeah, I saw, it works in the code sandbox. But strangely it still does not work in my code and there is no error. However, your solution apparently works. Thank you.
    – Ali EXE
    Commented Apr 15, 2022 at 7:54
  • Object.assign wont work, you can see that in vue console, it's stays apart from other data, which is pushed/popped from that array
    – Yu Da Chi
    Commented May 28, 2022 at 13:02
2

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>

3
  • It does not work. See this codesandbox
    – Ali EXE
    Commented Apr 15, 2022 at 7:39
  • @Ali EXE hey mate, what doesn't work ? when you click on load entire cart you get the right count Commented Apr 15, 2022 at 7:47
  • Yeah, it works now, because I have used the other answer. I used Object.assign not destructuring assignemnt.
    – Ali EXE
    Commented Apr 15, 2022 at 7:52

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.