Meituan-Dianping/mpvue · warning
Avoid replacing instance root $data. Use nested data propert
Error message
Avoid replacing instance root $data. Use nested data properties instead.
What it means
In development builds, the $data and $props instance accessors are defined with getters only plus a setter that warns. Assigning vm.$data = {...} is rejected (the getter value is unchanged) because replacing the root reactive data object would break reactivity and proxies.
Source
Thrown at packages/weex-vue-framework/factory.js:3308
handler = handler.handler;
}
if (typeof handler === 'string') {
handler = vm[handler];
}
return vm.$watch(keyOrFn, handler, options)
}
function stateMixin (Vue) {
// flow somehow has problems with directly declared definition object
// when using Object.defineProperty, so we have to procedurally build up
// the object here.
var dataDef = {};
dataDef.get = function () { return this._data };
var propsDef = {};
propsDef.get = function () { return this._props };
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function (newData) {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
);
};
propsDef.set = function () {
warn("$props is readonly.", this);
};
}
Object.defineProperty(Vue.prototype, '$data', dataDef);
Object.defineProperty(Vue.prototype, '$props', propsDef);
Vue.prototype.$set = set;
Vue.prototype.$delete = del;
Vue.prototype.$watch = function (
expOrFn,
cb,View on GitHub (pinned to 6c5d78ee04)
Solutions
- Mutate properties on $data instead: Object.keys(newData).forEach(k => this[k] = newData[k])
- Reset individual top-level keys to their initial values
- Use a factory that returns initial state and assign key-by-key
- Replace the component (v-if / :key) to get fresh state
Example fix
// before
resetState() { this.$data = initialState(); }
// after
resetState() {
const fresh = initialState();
Object.keys(fresh).forEach(k => { this.$data[k] = fresh[k]; });
} Defensive patterns
Strategy: validation
Validate before calling
function resetData(vm, initialFactory) {
const fresh = initialFactory();
Object.keys(fresh).forEach(k => { vm.$data[k] = fresh[k]; });
} Type guard
function isRootDataReplacement(stmt) {
return /\$data\s*=/.test(stmt);
} Prevention
- Never assign to this.$data or this.$props directly
- Reset state by reassigning individual keys
- Use :key changes or v-if to remount a component for a full state reset
When it happens
Trigger: Writing vm.$data = newObj or Object.assign used via direct replacement like this.$data = initialState() in a component, typically to 'reset' state.
Common situations: Trying to reset component state to initial values, copying state between components, or migration code that swapped whole data objects after Vue 1's looser behavior.
Related errors
- The computed property "${key}" is already defined in data.
- Avoid mutating a prop directly since the value will be overw
- data functions should return an object: https://vuejs.org/v2
- method "${key}" has already been defined as a data property.
- The data property "${key}" is already declared as a prop. Us
AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02).
Data as JSON: /api/errors/98786fcd3baf5406.
Report an issue: GitHub.