2
votes

I have the following code for a Vue.js component:

var list = Vue.component('list', {
  props: ['items', 'headertext', 'placeholder'],
  template: `
    <div class="col s6">
      <div class="search">
        <searchbox v-bind:placeholder=placeholder></searchbox>

        <ul class="collection with-header search-results">
          <li class="collection-header"><p>{{ headertext }}</p></li>
          <collection-item
            v-for="item in items"
            v-bind:texto="item.nome"
            v-bind:link="item.link"
            v-bind:key="item.id"
          >
          </collection-item>
        </ul>
      </div>
    </div>`,

  methods: {
    atualizaBibliografiasUsandoHipotese: function (value) {
      var query = gql`query {
        allHipotese(nome: "${value}") {
          id
          nome
          bibliografiasDestaque {
            id
            nome
            link
            descricao
          }
        }
      }`;
      client.query({ query }).then(function(results) {
        this.items = results['data']['allHipotese'][0]['bibliografiasDestaque'];
      }.bind(this));
    },
  }

});

And outside the component, in another javascript file, I call the atualizaBibliografiasUsandoHipotese method to make a query to the backend (GraphQL), and update the component. This works fine, however I get a warning message from Vue saying

[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: "items"

I made several attempts to fix this warning, but none of them worked. Anyone can help me on how can I fix this warning? Thanks

2
Since you are modifying the prop which is passed down from a parent component anyway, you should instead modify the data in the parent that is passed as a prop to the child component (so you are not mutating inherited props, but pre-existing parent data that is passed as prop). Think of it from a different angle: the inherited prop comes from a "source of truth", which is from the parent. So it makes sense to update the parent.Terry
Possible duplicate of Vue.js Changing propsRoy J

2 Answers

3
votes

As mentioned, you should not mutate props, instead you can do this:

var list = Vue.component('list', {
    props: ['items', 'headertext', 'placeholder'],
    template: `
      <div class="col s6">
        <div class="search">
          <searchbox v-bind:placeholder=placeholder></searchbox>
          <ul class="collection with-header search-results">
            <li class="collection-header"><p>{{ headertext }}</p></li>
            <collection-item 
              v-for="item in myItems"
              v-bind:texto="item.nome"
              v-bind:link="item.link"
              v-bind:key="item.id"
            >
            </collection-item>
          </ul>
        </div>
      </div>`,

    data: ()=> { return { 
            myItems: this.items
        }
    },

    methods: {
        atualizaBibliografiasUsandoHipotese: function (value) {
            // Your Code
            this.myItems = results['data']['allHipotese'][0]['bibliografiasDestaque'];
        }.bind(this));
    },
});

Notice that v-for is now looping over items in myItems.

1
votes

This is what you are looking for:

https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow

It even says:

This means you should not attempt to mutate a prop inside a child component. If you do, Vue will warn you in the console.