React Hooks:如何等待所有API数据获取完成后再执行setState?
你的问题核心是forEach里的异步回调不会等待Promise完成,循环刚执行完就立刻调用了setTableData,这时候getUserItemName的请求还处于pending状态,item.name根本没赋值,所以表格拿到的是不完整数据。
解决方法
1. 用Promise.all等待所有子请求完成
把遍历数据的forEach改成map,收集每个异步请求的Promise,再用Promise.all等待全部请求完成后再更新表格状态。同时统一用await语法,避免混用await和then导致逻辑混乱。
修改后的getInitialData代码:
const getInitialData = async () => { const username = user.username; // 先获取主数据 const mainResponse = await axios.get(`http://localhost:8080/api/sellers/${username}/someData`); const data = mainResponse.data; // 遍历每个item,发起子请求并等待全部完成 await Promise.all(data.map(async (item) => { item.name = await getUserItemName(username, item.id); })); // 所有数据补全后,再更新表格状态 setTableData(data); };
2. 可选:添加加载状态优化体验
可以新增一个isLoading状态,在数据加载完成前显示加载提示,避免表格空显示或展示不完整内容:
const [isLoading, setIsLoading] = useState(true); const [tableData, setTableData] = useState([]); const getInitialData = async () => { setIsLoading(true); const username = user.username; try { const mainResponse = await axios.get(`http://localhost:8080/api/sellers/${username}/someData`); const data = mainResponse.data; await Promise.all(data.map(async (item) => { item.name = await getUserItemName(username, item.id); })); setTableData(data); } catch (error) { console.error('数据加载失败:', error); // 这里可以加用户提示,比如alert('加载失败,请重试') } finally { setIsLoading(false); } };
对应的表格组件修改为:
{isLoading ? <div>加载中...</div> : <SortingTable ref={sortingTableRef} columns={TABLE_COLUMNS} data={tableData}/>}
原代码问题解析
forEach不会处理异步函数的返回值,哪怕你在回调里写了await,forEach也会直接跳过等待,继续执行下一次循环。所以循环结束时,所有getUserItemName的请求还在后台运行,此时setTableData传入的是还没补全name的原始数据,导致表格提前渲染。
而map会把每个异步回调的Promise收集成数组,Promise.all会等待数组中所有Promise都成功resolve后,才继续执行后续代码,确保所有item.name都赋值完成后再更新表格状态。
内容的提问来源于stack exchange,提问作者CK2002
相关产品推荐
相关产品推荐

