如何在mapped promise中一一修改useState数组

How to modify useState array one by one in mapped promise

我有 const [items, setItems] = useState<any[]>(itemsB.map(() => ({ loading: true })));

itemsB.map(async (itemB: any, index: number) => {
    searchItems(itemB).then(result => {
        const newItems = [...items]; // Ref A
        newItems[index] = result;
        setItems(newItems);
    })
})

因为内部函数是异步获取,项目以不可预测的顺序返回,我想在它们准备好后立即将它们添加到 items,将占位符加载对象更改为实际结果。这几乎可以做到这一点,但是 Ref A 中引用的 items 不会更新,因此它会循环更改每件事,然后在最后只显示最后一个检索到的项目。

如果我执行 Promise.all().then(),它会等到检索到所有项目后才执行 then 部分,所以我想知道如何在项目解析时设置它们。

也许这行得通:

itemsB.forEach(async (itemB: any) => {
    searchItems(itemB).then(result => {        
        setItems(prevItems => [...prevItems, result]);
    });
});

注意:这不应该在渲染函数中。你应该把它放在 componentDidMount/Update 或 useEffect 挂钩中。

对 setItems 的调用被分批处理以优化性能。如果之前的状态依赖于当前状态,请使用 setItems 的重载版本,它将 previousState 作为第一个参数。

searchItems(itemB).then(result => {
        setItems(items => {
                  const newItems = [...items]; // Ref A
                  newItems[index] = result;
                  return newItems;
        });
})

使用可以使用异步库来帮助您解决如下问题:

import eachOf from 'async/eachOf';

// assuming items is an array of async items
async.eachOf(itemsB, async (itemB: any, index: number, callback: ReturnType<string | void>) => {

    // Perform operation on itemB here.
    console.log('Processing item ' + itemB);
    
    try {
      const result = await searchItems(itemB);
      
      const newItems = [...items]; // Ref A
      // Settting-up new items
      newItems[index] = result;
      setItems(newItems);
      
      callback();
    }catch(e) {
      callback(e)
    }
}, function(err) {
    // If any of the item processing produced an error, err would equal that error
    if( err ) {
      // One of the iterations produced an error.
      // All processing will now stop.
      console.log('An item failed to process');
    } else {
      console.log('All items have been processed successfully');
    }
});