React require.context 多个组件重新渲染,加载时图像损坏

问题描述 投票:0回答:0

我正在画廊工作,对我来说最简单的方法是使用 require.context 导入数百张图像。在第一次使用 Effect 时,我从 2 个不同的文件夹导入相同数量的图像,一个带有缩略图,一个带有常规大小的图像。在第二个 useEffect 中导入后,我创建了一个新的对象数组,其中包含两种尺寸的图像、键、id 和 onLoad 函数的 src,该函数计算加载的图像并将它们的数量与图像数组长度进行比较,以便设置加载状态。新数组被直接映射和渲染。我专门为这个线程做了这个简化的例子,我试图让它尽可能短。

import { useState, useEffect } from "react";

const importAll = (r) => {
  return r.keys().map(r);
};

const Test = () => {
  console.log("Test Component");
  const [images, setImages] = useState([]);
  const [thumbnailImages, setThumbnailImages] = useState([]);
  const [combinedImages, setCombinedImages] = useState([]);
  const [loadedImagesCounter, setLoadedImagesCounter] = useState(0);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    console.log("First Use Effect");
    setImages(
      importAll(
        require.context(
          `../../assets/images/galleries/reportaz-images/`,
          false,
          /\.(jpe?g)$/
        )
      )
    );

    setThumbnailImages(
      importAll(
        require.context(
          `../../assets/images/galleries/reportaz-images-thumbnails/`,
          false,
          /\.(jpe?g)$/
        )
      )
    );
  }, []);

  const handleLoad = () => {
    setLoadedImagesCounter((prevCount) => prevCount + 1);
    if (loadedImagesCounter === combinedImages.length) setLoading(false);
  };

  useEffect(() => {
    console.log("Second Use Effect");
    setCombinedImages(
      images
        .map((image, index) => {
          return {
            src: image,
            thumbnailSrc: thumbnailImages[index],
          };
        })
        .map((image, index) => {
          return (
            <img
              style={{ width: "500px" }}
              src={image.src}
              onLoad={handleLoad}
              key={image.src}
              id={index + 1}
            />
          );
        })
    );
  }, [images, thumbnailImages]);

  const handleClick = () => {
    console.log(loadedImagesCounter);
    console.log(combinedImages.length);
  };

  return (
    <div style={{ display: "flex", flexDirection: "column" }}>
      <button onClick={handleClick}>test</button>
      {loading ? <p>Loading</p> : <p>Loaded</p>}
      {combinedImages}
    </div>
  );
};

export default Test;

我对这段代码及其工作方式有一些问题和疑虑。

  1. handleLoad 函数应该在图像加载时递增 1,并将数字与数组中的图像进行比较。初始状态设置为正在加载,并且它会很快更改为已加载,可能是在第一张图像开始加载时。我想 combinedImages 最初可能是空的 (0),计数器也是。我尝试将数字与包含相同数量项目的不同数组进行比较,这些项目应该曾经加载过 combinedImages 但状态从未更改为已加载。我有一个按钮,用于记录数组长度和加载图像的数量。我可以看到即使图像仍在加载,状态也已设置为已加载。加载所有内容后,按钮的控制台日志似乎显示图像数组和计数器的正确数量,它们是相等的。

2.我已经设置了一些 console.logs 来查看文档是如何呈现的,我很惊讶地看到大量的 console.logs。应该有那么多吗?

  Test Component
  test.js:16 First Use Effect
  test.js:44 Second Use Effect
  test.js:16 First Use Effect
  test.js:44 Second Use Effect
  test.js:8 Test Component
  test.js:44 Second Use Effect
76test.js:8 Test Component

  1. 除了找到图像加载的解决方案和正确更新我想知道的状态之外,所有这些都可以用更少的代码或更少的 useEffects 来实现吗?我试着把它放在一个里,但无法让它工作,除非我使用 await async 但我觉得我让它变得更加复杂。

编辑:我已经设法使加载状态正常工作。 当数组为空且计数器为 0 并立即触发状态更改时,代码首先运行。 我将比较移至 useState 并阻止它比较两个零。但是我相信一定有更好的方法来做到这一点。

  useEffect(() => {
    if (loadedImagesCounter === 0) return;
    if (loadedImagesCounter === images.length) {
      setLoading(false);
    }
  }, [loadedImagesCounter]);

reactjs image gallery react-context onload
© www.soinside.com 2019 - 2024. All rights reserved.