3

Codepen Demo

I have a component which has an location object as props. The argument I passed in is locations[index] which is a selected item from a locations array.

However, the component cannot react when the index change. As you can see in the demo, the JSON change as you click the button, but the component cannot update.

What's the best way to make the component reactive?

2 Answers 2

4

Your location component populates the province and city data properties in the mounted hook only. When the location prop changes, the mounted hook will not be called again, so you are left with stale data.

Use a computed property instead:

computed: {
  province() {
    return this.location.province;
  },
  city() {
    return this.location.city;
  }
}

Updated codepen

If you really do require province and city to be data properties (and not computed properties) then you will need to watch the location prop to update the properties:

data() {
  return {
    province: null,
    city: null
  }
},
watch: {
  location: {
    immediate: true,
    handler(loc) {
      this.province = loc.province;
      this.city = loc.city;
    }
  }
}
Sign up to request clarification or add additional context in comments.

8 Comments

You could just bind to location.province. No need for computed properties or watchers.
@FINDarkside I don't think that is true. In my case the property is not updated when binding directly... Initially the data is populated by an empty value in the child component, and when updating location.province in the parent it won't be reflected in the child... or am I missing something?
@Decade Moon If I don't have an object being passed as a property but just a value: like <Location :province="location.province" /> and I want the province value to be changed within the child (Location) component, I think computed properties do not work either. Is that correct? Event watching it does not help... Can I somehow make props of a primitive type reactive?
@Merc If you are passing a primitive value down through a prop, it cannot be updated directly by the child. The only way for the child to "update" it is to emit an event to the parent (this.$emit('update:province', value)) so the parent can update it. This is explained in the docs.
@DecadeMoon I do know about that, but I want it to be the other way around. The parent passes an initial prop (primitive) to a child, and then gets it's value updated. It should then inform the child and that one should update that primitive. So it's really the question written in the title but in my case I have primitives...
|
0

Nested items in your prop location won't be reactive, you'll need to use something like lodash deepClone :

<location :location.sync="_.deepClone(loc)"></location>

That's it, no need for watchers or anything else.

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.