如何在useEffect中循环调用接口并setState生成分类-子分类映射字典
问题原因
- 核心是异步执行顺序和变量污染/闭包两个问题:
Axios.get是异步操作,循环触发所有子分类请求后,JS不会等待请求返回就直接执行了位置2的打印,此时所有请求都还没返回,actual自然是空对象- 外层分类请求和内层子分类请求的返回值都命名为
p,变量名冲突,你在内层回调里写的p.data[i].category实际上取的是子请求的返回值,根本拿不到外层的分类名称;同时循环变量i存在闭包问题,拿到的永远是循环结束后的最终值,导致赋值的键名错误 - 每次回调里给
actual赋值时,因为请求返回顺序不固定,每次扩展的actual可能不是最新值,所以只会存最后一次成功返回的分类的子分类,就是你看到的位置1每次只有1个元素的问题
修复方案
用Promise.all等待所有子分类请求全部完成后再统一组装数据,代码如下:
useEffect(()=>{ Axios.get("http://localhost:3001/categories/get").then(async (categoryRes) => { setCategories(categoryRes.data) // 构造所有子分类请求的Promise数组 const subRequestList = categoryRes.data.map(categoryItem => { return Axios.get("http://localhost:3001/category/subcategories", { params : {category : categoryItem.category} }).then(subRes => { // 直接返回对应分类的键值对 return [categoryItem.category, subRes.data] }) }) // 等待所有请求完成 const allSubResult = await Promise.all(subRequestList) // 组装为你需要的字典结构 const actual = Object.fromEntries(allSubResult) // 此处执行setState即可拿到完整数据 setState(actual) }) }, [])
内容的提问来源于stack exchange,提问作者Víctor Donat
相关产品推荐
相关产品推荐

