7
votes

I have an component that I want to use on different pages. Well, it is working well till the first toggle. It shows like it used to, but when I click the 'Close' button, it closes, but console outputs :

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

found in

---> at src/components/Snackbar.vue at src/views/Login.vue

And after that it doesn't show up on click

Any way to fix this?

Snackbar.vue

<template>
  <v-snackbar v-model.sync="visible" :timeout="5000" bottom>
    {{ content }}
    <v-btn flat color="primary" @click.native="visible = false">Close</v-btn>
  </v-snackbar>
</template>

<script>
  export default {
    name: 'snackbar',
    props: [
      'visible',
      'content'
    ]
  }
</script>

Login.vue

<template>
  <div class="login">
    <Snackbar :visible="snackbar.visible" :content="snackbar.content"></Snackbar>
  </div>
</template>

<script>
  import Snackbar from '@/components/Snackbar.vue'
  export default {
    components: {
      Snackbar
    },
    data: function() {
      return {
        email: '',
        password: '',
        snackbar: {
          visible: false,
          content: ''
        }
      }
    },
    methods: {
      login: function() {
        if (this.email != '' && this.password != '') {
          // Do something
        } else {
          this.snackbar.content = 'Fields can\'t be empty';
          this.snackbar.visible = true;
        }
      }
    }
  }
</script>
1

1 Answers

4
votes

The console error is being triggered by this:

@click.native="visible = false"

The component is directly mutating the incoming prop. If you want to keep this level of control where the parent component controls the visibility you'll have to do it by having the click event emit an event, which the parent component receives and sets this.snackbar.visible = false thereby triggering a prop change and the child component is hidden.

<Snackbar :visible="snackbar.visible" :content="snackbar.content" 
     v-on:requestClose="close"></Snackbar>

<v-btn flat color="primary" @click.native="$emit('requestClose')">Close</v-btn>



methods: {
 close: function() {
   this.snackbar.visible = false;
 }
}