The problem is mutating a prop. In Vue, props are one-way (parent ➜ child). If the child needs a derived/parsed value, keep it in the child’s own data or compute it, but don’t overwrite the prop.
Here are clean ways to fix it.
If the parent passes a JSON string
Keep a local copy derived from the prop (never mutate the prop):
Vue.component('task', {
template: '#task-template',
props: {
// accept either a JSON string or an Array to be flexible
list: {
type: [String, Array],
required: true
}
},
data() {
return {
items: [] // local state, safe to mutate
};
},
created() {
this.syncFromProp();
},
watch: {
list: 'syncFromProp' // keep in sync if parent changes it
},
methods: {
syncFromProp() {
this.items = Array.isArray(this.list)
? this.list
: JSON.parse(this.list);
}
}
});
new Vue({ el: '.container' });
Use items in your template instead of list. Now you can freely push/splice items without warnings.
Even better: stop sending JSON strings
Since you’re using Laravel/Blade, bind real JS data from the parent:
<!-- Blade -->
<task :list='@json($list)'></task>
Then your component can just be:
Vue.component('task', {
template: '#task-template',
props: { list: { type: Array, required: true } },
// use `list` directly in the template if you don't need to mutate it,
// or copy to local data if you plan to edit:
data() {
return { items: this.list.slice() }; // local, editable copy
}
});
Why this is the rule
Props are controlled by the parent. If the child edits a prop, the next parent re-render will overwrite the child’s change. Hence the warning. The pattern is:
Parent owns data → passes down via props
Child requests changes → emits events (this.$emit('update', payload)) or uses v-model bindings so the parent updates the source of truth
If you later need two-way behavior, emit an event from the child and let the parent update list, or use v-model on a value/modelValue prop (Vue 3) instead of mutating props in the child.
date() { return {val: null}}and in the created part, your should assign the valuecreated() {this.val = JSON.parse(this.list)}