Sello Mkantjwa
Sello Mkantjwa

Reputation: 1915

Child prop not updating, even though the parent does

I have a pretty weird situation where a change in a child component's prop is not triggering a re-render.

Here is my setup. In the parent I have:

        <child :problemProp="proplemPropValue""></child>

In the child I have defined the prop:

{
    name: "Child",
    props: {
    problemProp: {
        type: [File], //yes it is a file 
        required: true
    }
}

and then I try to render it (still in the child component)

<template>
  <div id="dropzone-preview" class="file-row">
    {{problemProp}} <--This should just show the prop as a JSON string-->
  </div>
</template>

This is rendered correctly initially. But problemProp has a property upload.progress, and when I change it in the parent (I can confirm that it does change on the parent) it does NOT change in the child.

If I now add a second prop, dummyProp to the child:

   {
    name: "Child",
    props: {
    problemProp: {
        type: [File], //yes it is a file 
        required: true
    },
    dummyProp: {
        type: Number
    }
}

Now, when dummyProp changes, propblemProp also changes. What is going on here? Why does the change in dummyProp force a re-render but a change in propblemProp does not?

Upvotes: 2

Views: 476

Answers (1)

Bert
Bert

Reputation: 82489

The root of the problem appears to be that when you add a File object to the array, Vue fails to convert it into an observed value. This is because Vue ignores browser API objects:

The object must be plain: native objects such as browser API objects and prototype properties are ignored.

That being the case, any changes to that object will not be reflected in the Vue automatically (as you would typically expect) because Vue doesn't know they changed. That is also why it appears to work when you update dummyProp, because changes to that property are observed and trigger a re-render.

So, what to do. I've been able to get your bin to work by making a small change to the addedFile method.

addedfile(file){
  console.log(file);
  self.problemPropValues.push(Object.assign({}, file));
},

First, you don't need (or want) to use $data, just reference the property directly. Second, by making a copy using Object.assign, Vue properly observes the object and updates are now reflected in the child. It may be the case that you will need to use a deep copy method instead of Object.assign at some point, depending on your use case, but for now this appears to be working.

Here is the code I ended up with getting the bin to work (converted to codepen because I find working with codepen easier).

Upvotes: 2

Related Questions