如何在map遍历中通过ID请求数据并为数组元素添加新字段
问题分析与解决方案
你这段代码的核心问题是在map中使用async函数会返回Promise对象,导致shoppingList变成了Promise数组,渲染时根本取不到total_items的值;同时依赖loadComplete的第二个useEffect会重复触发,引发不必要的请求。
修复后的代码示例
export const ProductsList: FC<{}> = () => { const [shoppingList, setShoppingList] = useState<any>([]) const [isLoading, setIsLoading] = useState<boolean>(true) const getProductList = async () => { const response = await getShopList() return response.data._embedded.products } const getValues = async (id: string) => { const response = await getProductValues(id) // 加默认值避免接口返回异常导致渲染报错 return response.data._embedded.values[0]?.total_items || 0 } useEffect(() => { const fetchAllData = async () => { setIsLoading(true) try { // 先获取基础产品列表 const products = await getProductList() // 用Promise.all批量请求每个产品的额外数据 const productsWithTotal = await Promise.all( products.map(async (product) => ({ ...product, total_items: await getValues(product.id) })) ) setShoppingList(productsWithTotal) } catch (err) { console.error('加载数据失败:', err) } finally { setIsLoading(false) } } fetchAllData() }, []) if (isLoading) { return <div>加载中...</div> // 替换成你的自定义加载组件 } return shoppingList.map((product) => ( <Row key={product.id}> <Cell width={40}> <h1>{product.product_name}</h1> </Cell> <Cell width={30}> <Text weight='medium'> There is a total of ${product.total_items} items </Text> </Cell> </Row> )) }
关键修改说明
- 合并异步请求逻辑:把产品列表获取和额外数据请求放在同一个异步函数里,用
Promise.all批量处理所有产品的额外数据请求,确保所有数据返回后再更新状态 - 统一加载状态:用
isLoading替代原来的loadComplete,避免重复触发请求 - 增加异常处理:捕获请求错误并添加默认值,防止接口返回异常导致页面崩溃
- 移除冗余逻辑:删掉了第二个引发问题的
useEffect
可选优化方向
如果产品数量较多,批量请求可能导致接口压力过大,可以考虑:
- 尝试和后端沟通,提供批量查询接口(虽然你说无法合并,但可再确认)
- 实现懒加载:滚动到对应行时再请求该产品的
total_items数据 - 添加请求防抖(仅适用于非初始化场景)
内容的提问来源于stack exchange,提问作者AFAF
相关产品推荐
相关产品推荐

