I am wondering how React decides to re-render certain elements. I have an app where then the user switches tabs, I update an <AssetContainer>. Sometimes that container will contain an asset with the same document_id which is used for the key. I am noticing that when I create an asset, my effect runs to set a thumbnail URL to a blob fine. I switch tabs, create an asset with the same file and it makes another new blob. Then when I switch back to the first tab, it will NOT re-render. Despite being passed in a new asset.thumbnail.image, it treats it as the same. I should note asset.thumbnail.image is an array buffer. Does this make React disregard the value when looking for updates?
I have code like this:
<AssetContainer>
{assets.map((asset) => (
<Asset
key={asset.document_id}
thumbnail={asset.thumbnail!.image!}
thumbnailFormat={asset.thumbnail!.format!}
hasClaim={!!asset.provenance}
errors={asset.errors}
size="80px"
/>
)
)}
</AssetContainer>
Within <Asset> I have the following effect and code with <AssetView thumbnailUrl={thumbnailUrl} size={size}></AssetView> where that is defined as:
// The effect in Asset
useEffect(() => {
let blobUrl;
if (thumbnail) {
const imgData = Array.isArray(thumbnail)
? thumbnail
: new Uint8Array(Object.values(thumbnail));
const blob = new Blob([imgData], { type: thumbnailFormat });
blobUrl = URL.createObjectURL(blob);
// this is what stops firing every time i switch tabs which should re-render the elements based on new data in the tab
console.log('setting thumbnail url', blobUrl);
setThumbnailUrl(blobUrl);
}
return () => {
if (blobUrl) {
URL.revokeObjectURL(blobUrl);
}
};
}, []);
// The AssetView definition for the tag invocation above
const AssetView = styled.div`
display: inline-flex;
align-items: flex-end;
justify-content: flex-end;
flex-shrink: 0;
width: ${(props) => props.size};
height: ${(props) => props.size};
margin-right: 4px;
margin-bottom: 4px;
border-radius: 2px;
background-color: #434646;
background-image: ${(props) =>
props.thumbnailUrl ? `url("${props.thumbnailUrl}")` : 'none'};
background-size: contain;
background-position: center;
`;
The short version is this: Every time I switch tabs, <Asset> renders as expected. I see a console.log fire every time before the return of <AssetView>. However the useEffect of <Asset> is not firing when an array buffer prop is updating when the key is the same as before. Unsure why.
Update why doing [thumbnail] in the effect is not the answer This is not the issue as things update fine due to higher level components remounting. If I do this suggestion, every time i switch tabs it will re-run the use effect and generate a new blob URL which is not what I want. The behavior as-is is that in Tab A it will generate Blob-1 and in Tab B it will generate Blob-2. When I go back to Tab A I want Blob-1 but still get Blob-2.
I believe the issue is that the key is the same for both tabs (which I will fix), but am unsure how high one needs to go (if possible) for React to disregard the key. If it was only the key that was causing the caching, it shouldn't even generate Blob-2.