With the following component, I am getting an Error: [vuex] do not mutate vuex store state outside mutation handlers.
error:
<template> <div> <v-data-table :headers="headers" :items="items" :search="search" :key="tableKey" :pagination.sync="pagination" disable-initial-sort rowKey > <template slot="items" slot-scope="props"> <tr @click="clicked(props.item)" :class="{'secondary': props.item[rowKey]===selectedCode}"> <td v-for="header in headers" :key="header.value"> <BaseTableColumn :item="props.item" :index="header.value" :format="header.format" /> </td> </tr> </template> </v-data-table> </div> </template> <script> export default { name: 'BaseTable', props: { headers: Array, items: Array, search: String, tableKey: String, rowKey: String, }, data: () => ({ pagination: { rowsPerPage: 10, totalItems: -1, }, selectedCode: -1, }), components: { BaseTableColumn: () => import('@/components/base/BaseTableColumn'), }, methods: { clicked(row) { window.scrollTo(0, 0); this.selectedCode = row[this.rowKey]; this.$set(row, 'selected', true); this.$emit('rowClick', row); }, highlightFirst(items) { this.selectedCode = this.items[0][this.rowKey]; this.$set(this.items[0], 'selected', true); }, }, updated() { if (this.selectedCode === -1 && (typeof this.items === 'object') && this.items.length > 0) { this.highlightFirst(this.items); } }, }; </script>
For reference, here is headers.js
:
const headers = [ { text: 'Tenant Code', value: 'code', }, { text: 'Tenant ID', value: 'name', }, ]; export default headers;
and BaseTableColumn.vue
:
<script> export default { name: 'BaseTableColumn', props: { format: Function, item: Object, index: String, }, methods: { getText() { return this.item[this.index]; }, }, render(createElement) { if (this.$props.format) { return this.$props.format(this.item, this.index, createElement); } return createElement('div', this.getText()); }, }; </script>
The issue happens here:
this.$set(this.items[0], 'selected', true);
However, if I follow the docs like so:
<template> <div> <v-data-table :headers="headers" :items="tableRows" :search="search" :key="tableKey" :pagination.sync="pagination" disable-initial-sort rowKey > ... </template> <script> export default { name: 'BaseTable', props: { headers: Array, items: Array, search: String, tableKey: String, rowKey: String, }, ... computed: { tableRows() { const rows = [...this.items]; return rows; }, }, ... methods: { ... highlightFirst(items) { this.selectedCode = this.items[0][this.rowKey]; this.$set(this.tableRows[0], 'selected', true); }, }, updated() { if (this.selectedCode === -1 && (typeof this.tableRows === 'object') && this.tableRows.length > 0) { this.highlightFirst(this.tableRows); } }, }; </script>
I still get the errors, specifically in the updated()
hook and the highlightFirst()
method, even though I’m not referencing or mutating a prop. What else do I need to change to get rid of this error?
Advertisement
Answer
The way I eventually solved this problem was to emit an event and use the row
value in the parent component:
clicked(row) { window.scrollTo(0, 0); this.selectedCode = row[this.rowKey]; this.$emit('rowClick', row); },
However, to @Jesper’s point above, since then, I have been using Object.assign()
in cases like this where I need to break the link to Vuex.