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

useEffect调用图片预加载函数过快失效,重渲染后正常如何解决

问题根源

  1. 图片的onload回调是异步执行的,你同步调用handleLoading时,所有图片的加载请求才刚发出,onload回调还没有触发,counter自然还是0,所以判断条件永远无法满足,loading状态不会更新为false。
  2. 用来计数的counter是loadImages函数内部的局部变量,每次onload触发修改counter后,没有主动触发加载完成的判断逻辑,也不会触发组件更新,所以只有组件因为其他原因重渲染时,你才能看到counter的数值变化。

修复方案

你可以把加载完成的判断逻辑放到onload回调中,每次单张图片加载完成后都检查是否所有图片加载完毕,修改后的代码如下:

const { products } = useContext(WPContext);
const [productsList, setProductsList] = useState(products);
const [filteredList, setFilteredList] = useState(products);
const [loading, setLoading] = useState(false);


useEffect(() => {
    loadImages(products);
}, [products]); // 增加products作为依赖,避免上下文数据更新后逻辑不触发

const loadImages = (allProducts) => {
    let counter = 0;
    setLoading(true);
    const totalCount = allProducts.length;
    const newProducts = allProducts.map((product) => {
      const newImg = new Image();
      newImg.src = "https://via.placeholder.com/450x630";
      const handleLoadFinish = () => {
        counter += 1;
        if (counter >= totalCount) {
          setLoading(false);
          setFilteredList(newProducts);
        }
      }
      // 加载成功触发判断
      newImg.onload = handleLoadFinish;
      // 加载失败也触发判断,避免loading永久为true
      newImg.onerror = handleLoadFinish;

      return {
        ...product,
        acf: {
          ...product.acf,
          product_image: {
            ...product.acf.product_image,
            url: newImg.src,
          },
        },
      };
    });
};

额外注意事项

  • 如果后续商品数量会动态变化,建议用useRef存储counter变量,避免出现闭包陷阱
  • 如果需要对加载失败的图片做降级处理,可以在onerror回调中补充替换默认图的逻辑

内容的提问来源于stack exchange,提问作者Donnie Berry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:24:04