更新数组类型组件状态时部分值丢失的问题求助
解决Next.js Image组件onLoadingComplete并发更新状态丢失的问题
你遇到的问题是典型的React状态更新竞态:当多个onLoadingComplete回调同时触发时,它们都捕获了同一个旧的loadedImages状态值,导致后续更新会覆盖前面的操作,最终只保留了部分ID。
解决方法:使用函数式状态更新
React的setState支持传入函数,这个函数会接收最新的状态值作为参数,基于它生成新状态,能彻底避免并发更新时的状态覆盖问题。另外用Set存储已加载ID比数组更高效,判断是否已加载的操作复杂度从O(n)降到O(1),还能自动去重。
修改后的代码如下:
// 初始化状态用Set替代数组,更适合存储唯一ID const [loadedImages, setLoadedImages] = useState(new Set()); // 图片渲染逻辑 {(selectedActivity ? selectedActivity.images : calloutSet.allImages).map(imageReference => ( <div key={imageReference.id} className={styles.symbol}> <div className={styles.symbolImageContainer}> <Image fill={true} priority={true} onLoadingComplete={() => { setLoadedImages(prevSet => { // 基于最新的Set创建新集合,添加当前图片ID const newSet = new Set(prevSet); newSet.add(imageReference.id); return newSet; }); }} sizes="10rem, (max-width: 600px) 7.5rem" className={styles.symbol} src={imageReference.url} alt='Callout Set Symbol' /> </div> </div> ))} // 判断所有图片是否加载完成 const totalImages = (selectedActivity ? selectedActivity.images : calloutSet.allImages).length; const allLoaded = loadedImages.size === totalImages;
为什么这样能解决问题?
- 函数式更新确保每次状态更新都基于最新的状态快照,不会因为并发回调捕获旧状态而丢失更新。
Set的add操作自动处理重复ID,不需要额外写includes判断,代码更简洁高效。
验证方式
你可以在组件中渲染loadedImages.size,或者在更新后打印该值,会看到它会随着图片加载逐步增加到25,不会再出现ID丢失的情况。
内容的提问来源于stack exchange,提问作者okay
相关产品推荐
相关产品推荐

