You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:57:38