Reputation: 1915
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
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