我有一个简单的应用程序.我有一个上传读取到一个钩子多个图像.

useEffect(() => {
const CallMe = async () => {
  // files contains 2 images
  if (files.length > 0) {
    return Promise.all(
      files.map(async (file, idx) => {
        return new Promise(async (resolve, reject) => {
          try {
            const image = await resizeFile(file[idx]);
            console.log(image);

            resolve(image);
          } catch (error) {
            reject(error);
          }
        });
      })
    );
  }
};

CallMe().then((res) => {
  setThumbnails([...thumbnails, res]);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [files]);



 {thumbnails.length &&
    thumbnails?.map((img, idx) => {
      if (img)
        return (
          //ONLY ONCE IS SHOWN
          <img
            key={idx}
            src={img}
            alt="soso"
            height={100}
            width={100}
          ></img>
        );
    })}

enter image description here

推荐答案

主要问题在于:

setThumbnails([...thumbnails, res]);

有两个问题:

  1. 它使用初始值thumbnails(我猜是[]),而不是异步工作完成时的当前值.

  2. resarray,不是单个图像.

    相反,请使用回调表单,以便处理最新信息,并分发res:

    setThumbnails((previousThumbnails) => [...previousThumbnails, ...res]);
    

    这也将修复您 suppress 的ESLint错误.(这个错误很有帮助,我建议不要忽略它.)

以下是您可能需要考虑的一些其他问题:

  1. 你的map人看起来很可疑.你有

    files.map(async (file, idx) => {
    

    …但你正在做

    const image = await resizeFile(file[idx]);
    

    …但file已经是files的一个元素,所以除非files是数组of arrays,否则在那里只需要file而不是file[idx].(即使它是一个数组,使用第一个数组的索引0处的值,然后使用第二个数组的索引1处的值,这似乎很奇怪,以此类推.)

  2. async函数中使用new Promise.这是explicit promise creation anti-pattern,这里没有理由这么做.

  3. 您当前的代码忽略了调整文件大小的错误,而不是将其转储到控制台.我假设你真的想这么做,但一旦你用async/await,我会用try/catch来处理.

综上所述:

useEffect(() => {
    const CallMe = async () => {
        return Promise.all(files.map(async (file) => {
            try {
                return await resizeFile(file);
            } catch (error) {
                // Not really ideal to just ignore errors
                // Note this will leave an `undefined` in the returned array
                console.log(error);
            }
        }));
    };

    CallMe()
        .then((res) => {
            // Remove blank elements from the array
            res = res.filter(Boolean);
            // If we have any left, use them
            if (res.length) {
                setThumbnails((thumbnails) => [...thumbnails, ...res]);
            }
        })
        .catch((error) => {
            // ...handle/report error...
        });
}, [files]);

关于这一点,有几点需要注意:

<img
   key={idx}
   src={img}
   alt="soso"
   height={100}
   width={100}
></img>

因为我们知道你的数组会改变(如果files改变,如果它来自props,它可以改变),使用索引作为键将无法正常工作;从the react docs中可以看出:

如果项的顺序可能会更改,我们不建议对键使用索引.这可能会对性能产生负面影响,并可能导致组件状态问题.请参阅Robin Pokorny的文章以获得in-depth explanation on the negative impacts of using an index as a key.如果您 Select 不为列表项分配显式键,则React将默认使用索引作为键.

在我看来,他们说的不够强烈:你会得到重复的显示元素或没有从显示中删除的元素,等等.索引作为键对于static个列表来说只是一个有效的 Select .

最后,<img ...></img>在JSX中更惯用地写成<img .../>.(而且你永远不会用HTML写它;img是一个void元素.)

Reactjs相关问答推荐

eslint -无法解析模块的路径@web3modal/ethers/react导入/no-unresolved

有正确的方法来设置我的金牛座应用程序的图标吗?

CreateBrowserRouter将props 传递给父组件以验证权限

react 下拉菜单任务

两条react 路由的行为不同.有没有人能解释一下,我已经找了好几天了

在一个blog函数中调用setState钩子

Reaction Axios多部分/表单-数据数组不工作

Reactjs中的chartjs和reaction-chartjs-2的问题

强制 useEffect 仅运行一次

React - 如何重定向页面以显示数据修改?

未处理的拒绝 (TypeError):无法读取未定义的属性(读取协议)

我应该如何将字符串作为props 传递给 React 组件?

当 React 中的状态发生变化时如何停止重新加载谷歌 map ?

我正在try 将一组加载程序函数发送到我的路由,它抛出一个错误 Handler is not a funtion in a reactJs application

Redux,状态未定义

将 ref 赋予功能组件以使用内部功能

如何从一组对象映射 MUI 5 图标并更改其 colored颜色 ?

如何定制 React 热 toastr ?

react-query、react-hook-form 和表单验证

如何在 React x 中返回组件?