如何通过MongoDB ID数组批量从Products数据库获取对应数据?
批量获取MongoDB ID对应产品数据的问题
我有一组MongoDB ID:
const pId = ['62b3968ad7cc2315f39450f3', '62b37f9b99b66e7287de2d44']
先用forEach遍历这些ID:
pId.forEach((item)=>{ console.log(item) })
现在需要从products数据库获取每个ID对应的数据,尝试了以下React代码:
const [product, setProduct] = useState([{}]); useEffect(() => { pId?.forEach((item) => { const getProduct = async () => { try { const res = await userRequest.get("/products/find/" + item) setProduct(res.data) } catch (err) { console.log(err) } } getProduct() }) }, [pId])
我用useState([{}])是想把获取到的数据收集成对象数组,请问这种写法能不能实现批量获取每个ID对应的数据?当前写法存在什么问题?
问题分析与解决方案
当前写法的问题
- 状态被覆盖:每次调用
setProduct(res.data)都会直接替换掉之前的状态值,最终product只会保留最后一次请求返回的单个对象,完全达不到收集数组的目的。 - 初始状态冗余:
useState([{}])初始化了带空对象的数组,即便请求成功,这个空对象会一直留在数组里,导致数据不准确。 - 异步更新不可控:
forEach内的异步请求是并发执行的,状态更新顺序无法保证,还可能出现多次更新互相干扰的情况。
正确实现方式
要实现批量收集数据,需要保留原有状态并合理处理异步请求:
方式一:Promise.all批量请求(推荐)
一次性发起所有请求,完成后统一更新状态,效率更高且避免状态反复更新:
const [products, setProducts] = useState([]); // 初始化为空数组更合理 useEffect(() => { const fetchProducts = async () => { try { // 生成所有请求的Promise集合 const requestList = pId.map(item => userRequest.get(`/products/find/${item}`)); // 等待所有请求完成 const responses = await Promise.all(requestList); // 提取所有响应数据并更新状态 const productList = responses.map(res => res.data); setProducts(productList); } catch (err) { console.log(err); } }; pId?.length && fetchProducts(); // 确保ID数组非空时才发起请求 }, [pId]);
方式二:逐个请求并追加(仅特殊场景使用)
如果需要按顺序逐步更新状态,必须使用函数式更新确保基于最新状态修改:
const [products, setProducts] = useState([]); useEffect(() => { setProducts([]); // 每次ID变化时重置状态 pId?.forEach(async (item) => { try { const res = await userRequest.get(`/products/find/${item}`); // 函数式更新,避免状态覆盖 setProducts(prev => [...prev, res.data]); } catch (err) { console.log(err); } }); }, [pId]);
这种方式会多次触发组件重渲染,且请求完成顺序不固定时,数组顺序可能和pId不一致,非必要不使用。
内容的提问来源于stack exchange,提问作者Sahil
相关产品推荐
相关产品推荐

