如何在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');
}
});
我有
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');
}
});