Vuejs. Mutating prop in child component does not trigger warning. Wondering why Vuejs. Mutating prop in child component does not trigger warning. Wondering why vue.js vue.js

Vuejs. Mutating prop in child component does not trigger warning. Wondering why


Why does the prop mutation propagate to the parent in one case but not in the other ? Does it have maybe something to do with how javascript stores these variable ?

Yes. JavaScript reference variables such as objects and arrays don't change their references when you mutate their properties/values. This means the parent can access the changed properties too, because it also has access to the reference. And Vue only gives a prop mutation warning if the reference changes.

Warning:

this.prop = {}

No warning:

this.prop.id = 5

Is it good practice to use that trick ?

No. It's back to violating One way data flow in which data is passed down through props (to child) and up through events (to parent).


Ok, but why doesn't Vue warn about those changes?

Consider an object with 1000 properties or an array with 1000 items. Vue would have to deep check all 1000 for changes, and there is no quick way to do it because each item has to be individually compared to the old value. This would have performance implications and probably make many apps unusable.


Here is a comment on the subject from Vue team member Bolerodan:

Generally you shouldnt do that. This can / could cause unexpected bugs in your code. Generally you should make a copy of your object, modify that, then emit upwards to the parent (as you have mentioned in your last paragraph I believe). This is the method I take and is the general consensus of top down, emit up approach.


A very simple answer is that You are mutating a reference value and Vue doesn't track the whole reference instead it only checks for the address where the reference is. So if you re-assign that value then it will warn you.

A good example to understand the behaviour is understanding through variable declaration const

const makes your variable immutable but again same applies to it if the value is primitive in nature you can't change it, but if it's a reference you can't change it but you can definitely update a value located at the reference

const a = 'Foo' // Primitive valuea = 'bar' // voilation const b = { // Reference value name: 'Foo' }b.name = 'Bar' // It's goodconsole.log(b)b = {} // re-assign is voilation


Because the mutation prevention only catches direct assignments to the prop - it does not catch manipulations of its properties. The idea is that if you assign new values to the prop - you are assigning to the prop and not to the variable that is sitting in the parent Vue component which feeds the prop.

As soon as something in the parent component updates the feeding variable - the prop will be updated with this new value and the value that you have assigned to the prop in your child component will be overwritten.

If you feed the prop with an object and then mutate a property inside the prop in your child component - it will affect the same object inside the parent component. But if you try to assign a new object to the prop in your child component - you should get the same warning about mutating props.