Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Uzenkov's avatar

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders

Hello guys. Tell me, please, what I'am doing wrong.

Items.vue

<template>
  <el-table
    :data="items"
    border
    style="width: 100%">
    <el-table-column
      prop="name"
      label="Name">
    </el-table-column>
    <el-table-column
      prop="brand"
      label="Brand">
    </el-table-column>
    <el-table-column
      prop="status"
      label="Status"
      sortable>
      <template slot-scope="scope">
        <status-select
          :itemid="scope.row.id"
          :itemstatus="scope.row.status">
        </status-select>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>

  import Table from 'element-ui/lib/table';
  import TableColumn from 'element-ui/lib/table-column';

  export default {

  components: {
    'el-table': Table,
    'el-table-column': TableColumn
  },

    data() {
      return {
        items: [{
          name: '',
          brand: '',
          status: ''
        }]
      }
    },

    methods: {

      getItems() {
        axios.get('/api/items')
        .then(response => {
          this.items = response.data.items;
        })
        .catch(error => {
          console.log(error.response.data);
        });
      }

    },

    mounted() {
      this.getItems();
    }

  }


</script>

StatusSelect.vue

<template>
  <el-select v-model="status" @change="setStatus"  placeholder="Check status">
    <el-option label="Sale" value="sale"></el-option>
    <el-option label="Ordered" value="ordered"></el-option>
    <el-option label="Paid" value="paid"></el-option>
  </el-select>
</template>

<script>

import Select from 'element-ui/lib/select';
import Option from 'element-ui/lib/option';

export default {

  props: ['itemid', 'itemstatus'],

  components: {
    'el-select': Select,
    'el-option': Option
  },

  data() {
    return {

    }
  },

  computed: {
    status: {
      get() { return this.itemstatus },
      set(value) {
        this.itemstatus = value;
      }
    }
  },

  methods: {

    setStatus() {
      axios.patch('/api/items/'+this.itemid+'/status', { 'status': this.itemstatus })
      .then(response => {
        swal({
          buttons: false,
          text: response.data.message,
          icon: 'success',
          timer: 1000
        });
      })
      .catch(error => {
        console.log(error.response.data);
      });
    }

  },

  created() {
    this.status = this.itemstatus;
  }

}

</script>

I get this error: [Vue warn]: 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: "itemstatus".

0 likes
6 replies
Uzenkov's avatar

I solved the problem, moving everything into one component. But if someone answers my question, I will be grateful.

1 like
goatshark's avatar

@Uzenkov Any time you try to modify data that you've sent into a component as a "prop", Vue is going to get cranky and warn you not to do it. I think your warning was about modifying this.itemstatus in your computed status.get method. You might have even gotten away with it had you returned the value instead of trying to set the value of this.itemstatus in your computed property. I always use computed properties to return something instead of just using them as property-setting-logic. Does that make sense?

Uzenkov's avatar

@goatshark Thank you for the answer. It makes sense, but even if I pass the property directly to the template, the error does not disappear.

<el-select v-model="this.itemstatus" @change="setStatus"  placeholder="Check status">
  <el-option label="Sale" value="sale"></el-option>
  <el-option label="Ordered" value="ordered"></el-option>
  <el-option label="Paid" value="paid"></el-option>
</el-select>
PaulClarke's avatar

@Uzenkov The reason is that you are over writing a property.

You have passed 'item status' into the component as a prop. Then at the bottom of your code snippet you are over writing it according to the value of the selector which is why Vue is throwing the error.


  props: ['itemid', 'itemstatus'],


  computed: {
    status: {
      get() { return this.itemstatus },
      set(value) {
        this.itemstatus = value;
      }
    }
  },
}

To avoid this you need to assign an initial property. Something like...


  props: ['itemid', 'initialStatus'],


  data() {
    return {
        currentStatus: this.initialStatus,
    }
  },

  computed: {
    status: {
      get() { return this.currentStatus },
      set(value) {
        this.currentStatus = value;
      }
    }
  },
}

That way when you change status, the initial prop value is not altered and Vue will stop squawking. You could also assign currentStatus in a mounted method.

1 like
Uzenkov's avatar
Uzenkov
OP
Best Answer
Level 1

Problem solved.

I replaced it...

items: [{
  name: '',
  brand: '',
  status: ''
}],

...with this one.

items: [],

Thank you guys for the answers.

1 like

Please or to participate in this conversation.