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 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>
Sign up to request clarification or add additional context in comments.

4 Comments

Does not work. Please see my codesandbox.
Change line 59 to this: //cart = { ...newCart }; Object.assign(cart, newCart); Codesandbox
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.
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
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 Comments

It does not work. See this codesandbox
@Ali EXE hey mate, what doesn't work ? when you click on load entire cart you get the right count
Yeah, it works now, because I have used the other answer. I used Object.assign not destructuring assignemnt.

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.