0

I am generating a base64 string that represents an image and trying to pass that image data to a child component as the property of an object.

This is the class for my object that I want to pass to my child component. It has an image property as well as a few other properties. When my parent component changes otherData or id, things work fine. I will see the updated value in my child component. However, when image changes, I do not see the new image until I change a DIFFERENT property on my instance of MyDataModel! For example, if I change otherData, the new image suddenly appears on the screen. I am wondering if image is simply too big for Vue's change detection to handle. It's a base64 string to represent a 320x240 image, about 150KB in size. Hower, if I take out image and declare it as a string property on my parent component...then the child component shows the updated image every time without fail.

export default class MyDataModel { public id!: string; public image!: string; public otherData: string; constructor(init?: Partial<MyDataModel>) { Object.assign(this, init); } } 

In my parent component, this is how I declare a new object representing the data for my child component

private childData = new MyDataModel(); 

In my parent component, this is how I create the image:

const data = this.$refs.cameraCanvas.toDataURL('image/png'); this.capturedImageData = data; 

Then, I assin my image property to capturedImageData

this.childData.image = this.capturedImageData; 

childData is a property of my child component

<ChildComponent :data="childData"></ChildComponent> 

This is how I declare my data property in the child component

@Prop({required: true}) private data!: MyDataModel // MyDataModel is a typscript class with an image property 

Lastly, this is how I am trying to show the image

<b-img id="input-image" :src="data.image"></b-img> 

1 Answer 1

2

Ah! The classic case of no re-render in child component on update... my old nemesis 😏. In these situations what you want to do is to... kind of force (or more accurately coerce/trigger) a re-render of the child component on the update. Here's the simplest (and most vue friendly) way to do that:

Add a property to your parent components' data

/* ==== Parent component - script === */ data(){ return { // ... other properties here componentKey: 0, // this property - you can call it whatever, just let it be a number } } 

Bind that property to the child component

/* ==== Parent component - template === */ <ChildComponent :data="childData" :key="componentKey"></ChildComponent> 

Then, after assigning the capturedImageData, change the value of the property

this.childData.image = this.capturedImageData; this.componentKey += 1; 

This should trigger a re-render of the child component, and the new image should be displayed.

Side note, you can also do this to emitted events from the child component to trigger a self-re-render like so

<ChildComponent :data="childData" :key="componentKey" @someEmitEvent="componentKey += 1"></ChildComponent> 

It's a bit hacky, but it works.

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

2 Comments

Your solution works! However, I gotta say, that's really silly. Is this a known bug in Vue?
@Genoe - It's not really a bug per se, just kind of how Vue's reactivity and rendering engine work. This article and this other article go into further details if you're interested. Btw, if you don't mind, if it worked, could you kindly approve/upvote the answer? Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.