Avoid mutating a prop directly (render function)

167 Views Asked by At

just trying out creating components with the render function, but I am getting a weird warning:

enter image description here

Following component:

import Vue, { CreateElement, VNode } from 'vue'

export default Vue.extend({
  name: 'p-form-input',
  props: {
    type: String,
    name: String,
    value: {
      type: [ String, Number ]
    },
    placeholder: String,
    disabled: Boolean
  },
  data() {
    return {
      localValue: ''
    }
  },
  watch: {
    value(value) {
      this.localValue = value
    }
  },
  mounted() {
    this.localValue = this.$props.value
  },
  methods: {
    onInput(e: any) {
      this.localValue = e.target.value
      this.$emit('input', this.localValue)
    },
    onChange(e: any) {
      this.localValue = e.target.value
      this.$emit('change', this.localValue)
    }
  },
  render(h: CreateElement): VNode {
    return h('input', {
      class: 'form-control',
      domProps: {
        disabled: this.$props.disabled,
        type: this.$props.type,
        name: this.$props.name,
        placeholder: this.$props.placeholder,
        value: this.localValue
      },
      on: {
        input: this.onInput,
        change: this.onChange
      }
    })
  }
})

A v-model="inputValue" on the component does trigger a input/change on inputValue but im getting the warning?

Using vue 2.6.11!

Edit:

Don't mind the ts-ignore, it complains about no types found for it, so that's more cosmetic!!!

<template>
  <div id="app">
    <p-form-input type="text" name="some_input" v-model="inputValue" /> {{ inputValue }}
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
// @ts-ignore
import PFormInput from 'vue-components/esm/components/form-input'

export default Vue.extend({
  name: 'App',
  components: {
    PFormInput,
  },
  data() {
    return {
      inputValue: 'fdsdsfdsf'
    }
  }
});
</script>
1

There are 1 best solutions below

4
On

You have a prop named "value' and then you are using a variable named "value" in your method:

    onInput(e: any) {
      const value = e.target.value

      this.localValue = value

      this.$emit('input', value)
    },

Don't reuse the name "value". In fact, you don't even need that variable:

    onInput(e: any) {
      this.localValue = e.target.value
      this.$emit('input', this.localValue)
    },

Same thing for onChange:

    onChange(e: any) {
      this.localValue = e.target.value
      this.$emit('change', this.localValue)
    }