key相同场景下React是否会忽略ArrayBuffer类型props的重渲染触发?
React组件复用与重渲染逻辑
首先明确React的两个核心规则:
- 列表渲染时,React通过
key属性匹配前后两次渲染的元素,只要key相同、组件类型相同,就会复用已有的组件实例,不会销毁旧实例再创建新实例。 - 空依赖数组的
useEffect只会在组件第一次挂载完成后执行一次,后续不管prop如何更新,都不会重新触发,只有组件被销毁后再次挂载才会重新执行。
问题根因
- 你怀疑array buffer导致React忽略prop更新是不成立的:React对所有类型的prop都做浅比较(引用比对),只要你传入的
thumbnail是新的array buffer引用,React会正常触发Asset组件的重渲染,你能看到AssetView的渲染日志也验证了这一点,effect没触发和prop类型无关。 - 核心问题就是不同标签页的
Asset用了重复的document_id作为key:
切换标签时,React发现新的Asset列表里有和之前key相同的组件,就直接复用了旧的组件实例,不会触发重新挂载,所以你写的空依赖effect自然不会重新执行,实例里的thumbnailUrl状态还停留在上一次生成的结果,就出现了切回标签A显示的还是标签B的Blob-2的问题。 - 至于为什么会生成Blob-2:当你第一次切换到标签B时,如果此时旧的
Asset实例已经被销毁(比如之前标签A的内容被完全卸载),React会为标签B的同keyAsset创建新实例,触发effect生成Blob-2,之后再切回标签A,又会复用这个带Blob-2的实例,就出现了错乱。
解决方案
你预期不同标签页的同document_id资产各自独立保留自己的blob地址,最优解就是修改key的生成规则,保证全局唯一:
<AssetContainer> {assets.map((asset) => ( <Asset key={`${当前标签ID}-${asset.document_id}`} thumbnail={asset.thumbnail!.image!} thumbnailFormat={asset.thumbnail!.format!} hasClaim={!!asset.provenance} errors={asset.errors} size="80px" /> ) )} </AssetContainer>
这样不同标签的资产key不同,React会为每个标签的资产创建独立的组件实例,每个实例的effect只会在挂载时执行一次,生成各自的blob地址,切换标签时实例独立存储状态,不会出现错乱。
如果你不想修改每个Asset的key,也可以给AssetContainer加上标签ID作为key:
<AssetContainer key={当前标签ID}> {/* 原有内容 */} </AssetContainer>
这样切换标签时整个AssetContainer会销毁重建,内部所有资产组件也会重新挂载生成对应blob,不过如果资产列表很长的话,性能会比单独修改Asset的key差。
内容的提问来源于stack exchange,提问作者Dave Stein
相关产品推荐
相关产品推荐

