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

Maison012's avatar

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

I am trying to make my vue component as flexible as possibile, So i have some button and a search i need to use on all my table component . For now it is hard coded, but i wnat to make it more flexible, everything work until now except the search . I see an error like this on console

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: "query"

I know the problem is when i try to change the query input but does now know how to fix this problem. Does anyone know ?

//custom action buttons
import Button from './button.js';

export default {
    components: {
        'v-button': Button
    },

    props: [
        'selected',
        'query',
        'url'
    ],

    methods: {
        showModal() {
            this.$emit('showModal')
        },
        
        getRecord() {
            this.$emit('getRecord')
        },

        searchRecord() {
            this.$emit('searchRecord', this.query)
        },

        massDeleteRecord() {
            this.$emit('massDeleteRecord')
        }
    },

    template: `
        <div class="add-user py-4">
            <div class="d-flex">
                <div class="col-10">
                    <!-- Button trigger modal -->
                    <v-button type="success" @click.prevent="showModal" >
                        Add Record
                    </v-button>
                    <v-button type="primary" data-mdb-toggle="collapse" data-mdb-target="#collapseFilter" aria-expanded="false" aria-controls="collapseFilter" >
                        Filter
                        <i class="fa-solid fa-filter"></i>
                    </v-button>
                    <v-button v-show="selected.length>0" type="danger" class="dropdown dropdown-toggle" id="dropdownMenuButton" data-mdb-toggle="dropdown" aria-expanded="false" >
                            Action ({{selected.length}})
                    </v-button>
                    <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                        <li>
                            <a :href="url" class="dropdown-item btn-warning text-center">
                                Export
                                <i class="fa-solid fa-file-excel"></i>
                            </a>
                        </li>
                        <li>
                            <v-button @click="massDeleteRecord()" type="danger" class="dropdown-item text-center">
                                Delete
                                <i class="fa-solid fa-trash"></i>
                            </v-button>
                        </li>
                    </ul>
                </div>
                <div class="col-2">
                    <input v-model="query" type="search" class="form-control border-0" placeholder="Search" />
                </div>
            </div>
            
        </div>
    `,
}

User Table Component

import TableCustomAction from './partials/modules/TableCustomAction.js';
export default {
        components: {
            TableCustomAction,
        },
        
        data(){
            return {
                ....
                query: '',
                ....
                url: ''
            }
        },  
watch: {
            query: function(newQ, old) {
                if (newQ === "") {
                    this.getRecord();
                } else {
                    this.searchRecord();
                }
            },
        },

0 likes
2 replies
tykus's avatar

You are using the prop query as the v-model on an input; so obviously it will be mutated whenever the input is changed.

Use a computed property or data property based on the original prop instead - a data property is more appropriate in your case.

data: () => {
  return {
    data_query: this.query
  }
}
<input v-model="data_query" type="search" class="form-control border-0" placeholder="Search" />
Maison012's avatar

@tykus

export default {
    components: {
        'v-button': Button
    },

    data() {
        return {
            data_query: this.query
        }
    },

....
 <div class="col-2">
                    <input v-model="data_query" type="search" class="form-control border-0" placeholder="Search" />
 </div>

I tryed something like this based on your sugestion but it does not work

Please or to participate in this conversation.