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

React使用useState为遍历渲染的每个图片单独设置加载占位图的问题

问题核心原因

你当前定义的imageLoaded是全局共享的单个布尔状态,所有遍历渲染的图片都绑定同一个状态判断,自然只要任意一张图片加载完成触发setImageLoaded(true),所有图片的loading占位都会同时消失。

解决方案

方案1:在当前组件内用集合存储已加载图片标识

用Set存储所有加载完成的图片唯一ID(这里你用的是item.edition作为唯一key,直接复用即可):

  1. 修改状态定义:
// 存储所有已加载完成的图片edition
const [loadedEditions, setLoadedEditions] = useState(new Set());
  1. 修改渲染逻辑:
<div className="row">
  {shownImages.map((item) => (
    <div className="images-col" key={item.edition}>
      <div style={{ cursor: 'pointer' }} onClick={() => onPressImage(item.edition)}>
        <div className="img-container">
          <ul key={item.edition}>
            <li className="imgPlaceholder">
              {/* 只判断当前图片的edition是否在已加载集合里 */}
              {loadedEditions.has(item.edition) ? null : <img alt="" src="images/loading.gif"></img>}
              <img 
                style={loadedEditions.has(item.edition) ? {} : { display: 'none' }} 
                onLoad={() => {
                  // 加载完成后把当前edition加入已加载集合
                  setLoadedEditions(prev => {
                    const newSet = new Set(prev);
                    newSet.add(item.edition);
                    return newSet;
                  })
                }} 
                src={"https://imagelink.com/" + item.imagelink.split("/").reverse()[0]} 
              />
            </li>
          </ul>
        </div>
      </div>
    </div>
  ))}
</div>

方案2(更推荐):抽离独立图片组件

把单个图片卡片封装成独立组件,每个组件自己维护自身的加载状态,逻辑更清晰,互不干扰:

  1. 定义独立ImageCard组件:
const ImageCard = ({ item, onPressImage }) => {
  // 每个图片自己维护加载状态
  const [isLoaded, setIsLoaded] = useState(false);
  return (
    <div className="images-col">
      <div style={{ cursor: 'pointer' }} onClick={() => onPressImage(item.edition)}>
        <div className="img-container">
          <ul>
            <li className="imgPlaceholder">
              {isLoaded ? null : <img alt="" src="images/loading.gif"></img>}
              <img 
                style={isLoaded ? {} : { display: 'none' }} 
                onLoad={() => setIsLoaded(true)} 
                src={`https://imagelink.com/${item.imagelink.split("/").reverse()[0]}`} 
              />
            </li>
          </ul>
        </div>
      </div>
    </div>
  )
}
  1. 父组件直接调用:
<div className="row">
  {shownImages.map(item => (
    <ImageCard 
      key={item.edition} 
      item={item} 
      onPressImage={onPressImage} 
    />
  ))}
</div>

计数逻辑报错说明

Cannot create property 'current' on number '0'报错是因为你把普通数字变量当成useRef返回的ref对象使用了,如果你要统计加载总数需要用const loadCount = useRef(0)来定义计数器。不过计数逻辑只能实现所有图片加载完成后才统一隐藏所有loading,不符合你单张图片独立控制的需求。


内容的提问来源于stack exchange,提问作者Molly Hatchet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:36:04