Metikha Metikha - 24 days ago 8
Javascript Question

Vue2: warning: Avoid mutating a prop directly

I'm stuck in the situation where my child component (autocomplete) needs to update a value of its parent (Curve), And the parent needs to update the one of the child (or to completely re-render when a new Curve component is used)

In my app the user can select a Curve in a list of Curve components. My previous code worked correctly except the component autocomplete was not updated when the user selected another Curve in the list (the component didn't update its values with the value of the parent).

This problem is fixed now but I get this warning:


Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders. Instead, use a data or
computed property based on the prop's value. Prop being mutated:
"value"


The description of this warning explain exactly what behavior I expect from my components. Despite this warning, this code works perfectly fine !

Here is the code (parts of it have been removed to simplify)

// curve.vue
<template>
<autocomplete v-model="curve.y"></autocomplete>
</template>


<script>
import Autocomplete from './autocomplete'

export default {
name: 'Curve',
props: {
value: Object
},
computed: {
curve() { return this.value }
},
components: { Autocomplete }
}
</script>


// autocomplete.vue
<template>
<input type="text" v-model="content"/>
</template>

<script>
export default {
name: 'Autocomplete',
props: {
value: {
type: String,
required: true
}
},
computed: {
content: {
get() { return this.value },
set(newValue) { this.value = newValue }
}
}
}
</script>


A lot of people are getting the same warning, I tried some solutions I found but I was not able to make them work in my situation (Using events, changing the type of the props of Autocomplete to be an Object, using an other computed value, ...)

Is there a simple solution to solve this problem ? Should I simply ignore this warning ?

Answer Source

You can ignore it and everything will work just fine, but it's a bad practice, that's what vue is telling you. It'll be much harder to debug code, when you're not following the single responsibility principle.

Vue suggests you, that only the component who owns the data should be able to modify it.

Not sure why events solution ($emit) does not work in your situation, it throws errors or what?

To get rid of this warning you also can use .sync modifier: https://vuejs.org/v2/guide/components.html#sync-Modifier