Home > database >  Unexpected mutation Vue.js
Unexpected mutation Vue.js

Time:10-20

This is my Searchcomponent, but it throws an Unexpected Mutation of "query" prop error, and I tried this way but still get an error.

    <template>
      <div >
        <input
          type="text"
          v-model="query.name" // this is the error
          
          placeholder="Search"
        />
    <div v-if="query.name.length > 3">
        <select v-model="query.status" > // This is the error
          <option value="alive">Alive</option>
          <option value="dead">Dead</option>
          <option value="unknown">Unknown</option>
        </select>
    </div>
    
      </div>
    </template>
    
    <script>
    export default {
      props: {
            query: String
      }
    };
    </script>
    
    <style scoped>
    .input {
      font-family: Roboto;
      font-size: 16px;
      height: 56px;
      border-radius: 8px;
      width: 326px;
      padding: 16px 48px;
      line-height: 150%;
      border: 1px solid rgba(0, 0, 0, 0.5);
      background: url("../assets/search.svg") no-repeat scroll 10px center;
      outline: none;
    }
    .input::placeholder {
      line-height: 150%;
      color: rgba(0, 0, 0, 0.5);
    }
    
    .select {
      font-family: Roboto;
      line-height: 19px;
      color: rgba(0, 0, 0, 0.6);
      font-size: 16px;
      height: 56px;
      border-radius: 8px;
      width: 240px;
      padding-left: 14px;
      border: 1px solid rgba(0, 0, 0, 0.5);
      outline: none;
      background: url("../assets/arrow-up-down.svg") no-repeat scroll 90% center;
    }
    select {
      -webkit-appearance: none;
      -moz-appearance: none;
      text-indent: 1px;
      text-overflow: "";
    }
    .searchbar {
      display: flex;
      gap: 20px;
      margin: 16px auto 61px;
    }
    </style>

This is the view Characters, that use the component Search and pass the query data

<template>
  <div >
    <img src="../assets/characterLogo.svg" alt="logo-character"  />
    <CharacterSearchBar :query="query" />

    <p v-if="query.name.length < 4">
      Enter 4 characters
    </p>

    <div  v-if="query.name.length > 3">
      <CharacterCard
        v-for="character in results"
        :key="character.id"
        :character="character"
      />
    </div>
    <div v-if="error" >
      Sorry, dont have any result
    </div>
    <div v-if="query.name.length > 3">
      <button @click="loadMore" >Load More</button>
    </div>
  </div>
</template>

<script>
import CharacterCard from "../components/CharacterCard.vue";
import CharacterSearchBar from "../components/CharacterSearchBar.vue";
import getData from "../composables/getData";
import { APISettings } from "../api/config";
import { watchEffect } from "vue";
import getFilterResults from "../composables/getFilterResults";
export default {
  components: { CharacterCard, CharacterSearchBar },
  setup() {
    const { charactersUrl } = APISettings;
    const { results, info, loadMore } = getData(charactersUrl);
    const { fetchQuery, query, error } = getFilterResults(
      charactersUrl,
      results,
      info
    );

    watchEffect(loadMore)

    watchEffect(fetchQuery);
    return { results, info, loadMore, query, error};
  },
};
</script>

These are the errors that I get

error Unexpected mutation of "query" prop vue/no-mutating-props

error Unexpected mutation of "query" prop vue/no-mutating-props

I would greatly appreciate your help

CodePudding user response:

You have the v-model in the input set to query.name, which means that query will be mutated when you change the input value. Since query is a prop, you can't do this.

CodePudding user response:

Additional to @Ian answer, To fix this warning, one solution is to create a computed property with get with the value of query prop and set with an emit event to the parent component to update the query prop from the parent, and in you html you can use the computed value instead of prop value

    <template>
      <div >
        <input
          type="text"
          v-model="compQuery.name" // this is the error
          
          placeholder="Search"
        />
    <div v-if="query.name.length > 3">
        <select v-model="compQuery.status" > // This is the error
          <option value="alive">Alive</option>
          <option value="dead">Dead</option>
          <option value="unknown">Unknown</option>
        </select>
    </div>
    
      </div>
    </template>
    
    <script>
    export default {
      props: {
            query: String
      },
      computed: {
        compQuery: {
          get () { return this.query },
          set (value) { this.$emit('update:query', value) },
        },
      },
    };
    </script>

And in the parent component of this component, you can pass the prop as v-model:prop="prop"

For example

<child v-model:query="query" />
  • Related