You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新数组类型组件状态时部分值丢失的问题求助

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:52:43