I'm stuck in the situation where my child ponent (autoplete) needs to update a value of its parent (Curve), And the parent needs to update the one of the child (or to pletely re-render when a new Curve ponent is used)
In my app the user can select a Curve in a list of Curve ponents. My previous code worked correctly except the ponent autoplete was not updated when the user selected another Curve in the list (the ponent 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 ponent re-renders. Instead, use a data or puted property based on the prop's value. Prop being mutated: "value"
The description of this warning explain exactly what behavior I expect from my ponents. Despite this warning, this code works perfectly fine !
Here is the code (parts of it have been removed to simplify)
// curve.vue
<template>
<autoplete v-model="curve.y"></autoplete>
</template>
<script>
import Autoplete from './autoplete'
export default {
name: 'Curve',
props: {
value: Object
},
puted: {
curve() { return this.value }
},
ponents: { Autoplete }
}
</script>
// autoplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autoplete',
props: {
value: {
type: String,
required: true
}
},
puted: {
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 Autoplete to be an Object, using an other puted value, ...)
Is there a simple solution to solve this problem ? Should I simply ignore this warning ?
I'm stuck in the situation where my child ponent (autoplete) needs to update a value of its parent (Curve), And the parent needs to update the one of the child (or to pletely re-render when a new Curve ponent is used)
In my app the user can select a Curve in a list of Curve ponents. My previous code worked correctly except the ponent autoplete was not updated when the user selected another Curve in the list (the ponent 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 ponent re-renders. Instead, use a data or puted property based on the prop's value. Prop being mutated: "value"
The description of this warning explain exactly what behavior I expect from my ponents. Despite this warning, this code works perfectly fine !
Here is the code (parts of it have been removed to simplify)
// curve.vue
<template>
<autoplete v-model="curve.y"></autoplete>
</template>
<script>
import Autoplete from './autoplete'
export default {
name: 'Curve',
props: {
value: Object
},
puted: {
curve() { return this.value }
},
ponents: { Autoplete }
}
</script>
// autoplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autoplete',
props: {
value: {
type: String,
required: true
}
},
puted: {
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 Autoplete to be an Object, using an other puted value, ...)
Is there a simple solution to solve this problem ? Should I simply ignore this warning ?
Share Improve this question asked Sep 23, 2017 at 19:48 MichaelMichael 5396 silver badges12 bronze badges 1- 1 in the doc: for a ponent to work with v-model you need to accept a value prop and emit an input event !! – hannes neukermans Commented Sep 23, 2017 at 21:29
2 Answers
Reset to default 4you can try is code, follow the prop
-> local data
-> $emit local data to prop
flow in every ponent and ponent wrapper.
ps: $emit('input', ...) is update for the value(in props) bind by v-model
// curve.vue
<template>
<autoplete v-model="curve.y"></autoplete>
</template>
<script>
import Autoplete from './autoplete'
export default {
name: 'Curve',
props: {
value: Object
},
data() {
return { currentValue: this.value }
}
puted: {
curve() { return this.currentValue }
},
watch: {
'curve.y'(val) {
this.$emit('input', this.currentValue);
}
},
ponents: { Autoplete }
}
</script>
// autoplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autoplete',
props: {
value: {
type: String,
required: true
}
},
data() {
return { currentValue: this.value };
},
puted: {
content: {
get() { return this.value },
set(newValue) {
this.currentValue = newValue;
this.$emit('input', this.currentValue);
}
}
}
}
</script>
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 ponent 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://v2.vuejs/v2/guide/ponents.html#sync-Modifier