8

I have a simple question but I can't find the answer to it. This code (that belongs to a child component? is a good practice?

 export default {
  name: 'Wish',
  props: ['wish'],
  data () {
    return {
      isEditing: false
    }
  },
  methods: {
    completeWish () {
      this.wish.done = true
    },
   ...

Or I should update the done property of wish object in the parent using emit?

Thanks

3
  • 1
    This is a design choice. Sometimes you want to update the object in the child, sometimes you want to emit a change. Commented Dec 9, 2017 at 18:17
  • Props are read-only. (or at least you shouldn't try to change them) Commented Dec 9, 2017 at 20:45
  • Is it clearer to you now? Commented Dec 14, 2017 at 9:07

3 Answers 3

10

As Amade mentioned is a bad practice.

You should use events in order to accomplish it properly from a design point of view.

<script>
  export default {
    name: 'Wish',
    props: ['wish'],
    methods: {
      completeWish () {
        this.$emit('wish-is-completed')
      }
    }
  }
</script>

And then in parent you have v-on:wish-is-completed="handleCompletedWish" like:

// Parent template
<template>
  <wish v-on:wish-is-completed="handleCompletedWish"></wish>
</template>

EDIT:

I understand the answer was downvoted because you actually are able to mutate properties of props (not a direct prop reference) and don't get a warn when you do that.

Does it mean you should do that?

No.

Props are created for one-directional data flow purpose. When you mutate props to notify a parent of something, it quickly leads to having hard to maintain state changes, because they are not implicit. Use events for child->parent communication as official documentation suggest in such cases.

All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.

Sign up to request clarification or add additional context in comments.

1 Comment

"it quickly leads to having hard to maintain state changes". I keep reading this everywhere but can anyone provide an actual example of this leading to issues? I have yet to come across one.
1

Vue docs advise against mutating the props in the child component:

All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.

In addition, every time the parent component is updated, all props in the child component will be refreshed with the latest value. This means you should not attempt to mutate a prop inside a child component. If you do, Vue will warn you in the console.

So based on this I would tend to say it's a bad practice.

6 Comments

Vue will not warn you if you change a property of an object passed in as a prop.
It is phrased poorly. They mean that you should not attempt to mutate the reference of a prop. If you have a prop wish, the docs mean that you should not attempt to do things like this.wish = 'a new wish'
At the end of the section I quoted it says: "Note that objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself inside the child will affect parent state". Doesn't it go against the 'one-way data flow' principle?
@Bert you still should not do that because props are for one-directional data flow purpose. You won't get a warn but using it quickly leads to having hard to maintain state changes, because they are not implicit. Always use events for child->parent communication.
As I said under the question, it's a design decision. This is an opinionated issue. There's no right answer.
|
0

documentation:

Due to the limitations of modern JavaScript (and the abandonment of Object.observe), Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive

if you want add or change property use Vue.set like this:

this.$set(this.wish, 'done', true)

see example App: https://3xyx386q65.codesandbox.io/setProps

see example code (open components/setProps/childComponent.vue): https://codesandbox.io/s/3xyx386q65

note! wish init as Object! See components/setProps/setProps.vue in example code

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.