Repository: vuejs/eslint-plugin-vue

Issue #1371: vue/no-mutating-props option: {"propProps": false}
Created: 2020-12-09T06:46:49Z
What rule do you want to change?
vue/no-mutating-props
Does this change cause the rule to produce more or fewer warnings?
A new,  {"propProps": false} option would cause it to produce fewer warnings.
How will the change be implemented? (New option, new default behavior, etc.)?
New option: {"propProps": false} (i.e. Don't error when mutating prop properties)
Please provide some example code that this change will affect:

<template>
  <div>
    <input type="range" v-model.number="point.x" >
    <input type="range" v-model.number="point.y" >
  </div>
</template>
<script>
  export default {
    props: {
      point: {
        type: Object,
        required: true
      }
    },
  }
</script>
What does the rule currently do for this code?
Trigger an error
What will the rule do after it's changed?
When the default option is set ({"propProps": true}), the error will trigger. When the option is set as {"propProps": false}, it will not trigger an error.
Additional context
(Note there are some issues in the past suggesting this rule be loosened (#1339 , #1314; cc @leosdad @pimlie @decademoon ); here I'm suggesting an option be added instead)
My main reason for wanting an option here, is that modifying the reference of a prop (e.g. this.myProp = 3) will cause actual run-time warnings from Vue, cause unexpected behaviour, and is deprecated:

Due to the new rendering mechanism, whenever the parent component re-renders, the child component’s local changes will be overwritten. - https://vuejs.org/v2/style-guide/#Implicit-parent-child-communication-use-with-caution

Here's the warning Vue throws:
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: "number"
Modifying the value of a prop (but leaving the reference the same) (e.g. this.myProp.x = 3), does not throw runtime warnings, and (I believe) does not cause any unexpected behaviour—it's just a code style decision. As long as the actual reference to the object remains unaltered, Vue should not have any issues.
Here's a sandbox with these two cases for reference: https://codesandbox.io/s/elegant-lederberg-p1ilc
(Note: This is the same way that const behaves in JS, so shouldn't be unexpected to most developers:
const x = 3;
x = 7; // Error!

const y = {};
y.foo = 3; // This is fine; it's the _reference_ that's const, not the value.
y = 20; // Error
)
I would love it if I could configure linting to error for reference prop modifications (which I need to fix), but to ignore value prop modifications (which I often prefer using in my code). If an option is added called, say {"propProps": true}, then I would use it instead of disabling the rule entirely.

P.S. How would one implement my code snippet above without prop value modification? The nicest way I can think of is something like this, which doesn't look particularly better to me.
<template>
  <div>
    <input type="range" v-model.number="x" >
    <input type="range" v-model.number="y" >
  </div>
</template>
<script>
  export default {
    props: {
      value: {
        type: Object,
        required: true
      }
    },
    data() {
        return {
            x: this.value.x,
            y: this.value.y,
        };
    },
    watch: {
        // Duplicate; could create a `mounted` method and use `$watch` to watch everything
        x(newVal) { this.$emit('input', { x: newVal, y: this.y } },
        y(newVal) { this.$emit('input', { x: this.x, y: newVal } },
    }
  }
</script>
(Similar to https://simonkollross.de/posts/vuejs-using-v-model-with-objects-for-custom-components )

Duplicate issue #2080: False positive on vue/no-mutating-props
Created: 2023-01-24T17:32:39Z
Checklist

 I have tried restarting my IDE and the issue persists.
 I have read the FAQ and my problem is not listed.

Tell us about your environment

ESLint version: 8.32.0
eslint-plugin-vue version: 9.9.0
Node version: 16.18.1
Operating System: Mac

Please show your full configuration:

/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution');

module.exports = {
  root: true,
  ignorePatterns: ['coverage/*'],
  extends: [
    'plugin:vue/essential',
    'eslint:recommended',
    '@vue/eslint-config-typescript/recommended',
    '@vue/eslint-config-prettier',
    'plugin:json/recommended',
  ],
  rules: {
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
  },
};
What did you do?

<!-- ------------- Parent.vue -------------- -->
<template>
  <child-comp v-model="homeAddress" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import ChildComp from './Child.vue';

export default defineComponent({
  name: 'ParentComp',
  components: {
    ChildComp,
  },
  data: () => ({
    homeAddress: { address1: '123 Main st' },
  }),
});
</script>

<!-- ------------- Child.vue -------------- -->
<template>
  <div>
    Enter street address
    <input v-model="value.address1" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'ChildComp',
  props: {
    value: {
      type: Object,
      required: true,
    },
  },
});
</script>

What did you expect to happen?
No ESLint errors.
What actually happened?
Received the error for Child.vue: "4:21  error  Unexpected mutation of "value" prop  vue/no-mutating-props".
Child does not mutate the prop, it mutates a property inside the passed prop.  Vue does not give any error at runtime about mutating a prop.  The test cases for this rule seem to indicate that this should be valid... but the rule is complaining.
Repository to reproduce this issue
(https://github.com/asselin/eslint-vue-bug)

Closing comment (2023-01-24T17:34:51Z): Duplicate of #1371