Chris
Chris

Reputation: 3461

pushed items to array seem to be reactive to old object

I am facing an issue where after I push an object to an array it will be reactive to changes.

// actions.js
export const addToCart = ({ commit }) => {
    commit('addToCart'); // properly commits to change the state

    setTimeout(function () {
        commit('resetToppings');
    }, 10000);
};


// mutations.js
export const addToCart = (state) => {
    state.cart.push(state.orderItem);
};

export const resetToppings = (state) => {
    state.orderItem.toppings = [];
};


// state.js
cart: [],
orderItem: {
    quantity: 1,
    toppings: [],
},

The orderItem gets properly pushed to the cart, but 10 seconds later when I resetToppings, it resets the toppings inside the cart as well as in the orderItem.

How can I make sure that resetToppings does not mutate anything inside cart?

Upvotes: 0

Views: 177

Answers (1)

acdcjunior
acdcjunior

Reputation: 135762

When you push state.orderItem you add a reference to it in the array. So when state.orderItem changes, the element inside the array changes, because it (the element inside the array) is actually still pointing to the same (state.orderItem) object.

You can push a shallow clone of the orderItem object instead:

// mutations.js
export const addToCart = (state) => {
    state.cart.push({...state.orderItem});
};

This way what is added to the array is a different object.


Note: you can do:

state.cart.push({...state.orderItem});

But this will only work if you never remove/add elements from/to the toppings array directly after the addToCart is called. That is, if you call resetToppings before adding new elements to toppings (which will work because resetToppings assigns a new array).

If that's not always the case, I mean, if you sometimes edit the toppings array directly after the addToCart is called, you might want to clone it as well:

state.cart.push(Object.assign({...state.orderItem}, {toppings: [...state.orderItem.toppings]}});

Upvotes: 2

Related Questions