{"record":{"id":"3e0ca16bb96d6fd3","repo":"Meituan-Dianping/mpvue","slug":"props-is-readonly-3e0ca1","errorCode":null,"errorMessage":"$props is readonly.","messagePattern":"\\$props is readonly\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/core/instance/state.js","lineNumber":305,"sourceCode":"\nexport function stateMixin (Vue: Class<Component>) {\n  // flow somehow has problems with directly declared definition object\n  // when using Object.defineProperty, so we have to procedurally build up\n  // the object here.\n  const dataDef = {}\n  dataDef.get = function () { return this._data }\n  const propsDef = {}\n  propsDef.get = function () { return this._props }\n  if (process.env.NODE_ENV !== 'production') {\n    dataDef.set = function (newData: Object) {\n      warn(\n        'Avoid replacing instance root $data. ' +\n        'Use nested data properties instead.',\n        this\n      )\n    }\n    propsDef.set = function () {\n      warn(`$props is readonly.`, this)\n    }\n  }\n  Object.defineProperty(Vue.prototype, '$data', dataDef)\n  Object.defineProperty(Vue.prototype, '$props', propsDef)\n\n  Vue.prototype.$set = set\n  Vue.prototype.$delete = del\n\n  Vue.prototype.$watch = function (\n    expOrFn: string | Function,\n    cb: any,\n    options?: Object\n  ): Function {\n    const vm: Component = this\n    if (isPlainObject(cb)) {\n      return createWatcher(vm, expOrFn, cb, options)\n    }\n    options = options || {}","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/src/core/instance/state.js#L287-L323","documentation":"Vue dev-mode warning triggered by the $props setter installed in stateMixin. Props are owned by the parent component; mutating or replacing them from the child would break one-way data flow, so Vue makes $props read-only and warns on any assignment.","triggerScenarios":"this.$props = {...}; vm.$props.someProp = value; or generic code that loops over instance keys and assigns (e.g. deep-cloning state back onto the instance).","commonSituations":"Trying to 'localize' or edit prop values instead of copying them into data; deserialization/restore routines that blindly assign all collected keys; misunderstanding one-way data flow in child components.","solutions":["Assign to a local data property initialized from the prop, then mutate that","Emit an event to the parent and let the parent update the prop","Use a computed that transforms the prop instead of writing back to it"],"exampleFix":"// before\nmounted() { this.$props.count = 0 }\n// after\nexport default {\n  props: ['count'],\n  data() { return { localCount: this.count } }\n}","handlingStrategy":"fallback","validationCode":"function isPropWrite(vm, key) { return vm.$options && key in (vm.$options.props || {}) }","typeGuard":"function canAssignToInstance(vm, key) { return !(vm.$options && key in (vm.$options.props || {})) }","tryCatchPattern":null,"preventionTips":["Treat all props as read-only in child components","Copy prop values into local data when mutation is needed","Communicate upward with $emit for prop changes"],"tags":["vue","reactivity","props","readonly","one-way-data-flow"],"backgroundTag":"readonly-assignment","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}