React中如何正确在循环内调用useFetch Hook实现批量数据请求
报错原因
React 官方明确规定所有 Hook 必须在组件顶层作用域调用,禁止在循环、条件判断、嵌套函数内执行 Hook。你在 for 循环中调用 useFetch 违反了这一规则,因此触发了编译报错。
正确实现方案
你不需要循环调用 useFetch,可以在拿到周期长度后,通过 useEffect 手动发起批量请求,示例代码如下:
import { useState, useEffect } from 'react'; // 原有拉取周期列表的逻辑保持不变 const [period_waterfall, periodLoading, periodError] = useFetch(`/company/${firminfo.code}/periods`); // 新增状态存储批量拉取的waterfall数据、加载态、错误态 const [waterfallList, setWaterfallList] = useState([]); const [waterfallLoading, setWaterfallLoading] = useState(false); const [waterfallError, setWaterfallError] = useState(null); useEffect(() => { // 周期列表未加载完成时跳过执行 if (!period_waterfall?.periods?.length) return; const periodLength = period_waterfall.periods.length; setWaterfallLoading(true); const fetchAllWaterfall = async () => { try { // 生成所有请求的Promise数组 const requestList = Array.from({ length: periodLength }, (_, index) => { return fetch(`/company/${slug}/waterfall?colIndexOffset=${index}`).then(res => { if (!res.ok) throw new Error(`请求${index}失败`); return res.json(); }); }); // 并发执行所有请求 const resultList = await Promise.all(requestList); setWaterfallList(resultList); } catch (err) { setWaterfallError(err); } finally { setWaterfallLoading(false); } }; fetchAllWaterfall(); }, [period_waterfall, slug]); // 依赖项需完整声明
可选优化点
- 如果请求数量较多,可将
Promise.all替换为分批请求逻辑,避免触发浏览器并发请求数限制 - 若需要支持单个请求失败不中断整体拉取,可以给每个请求单独包一层
catch,返回错误标记而非直接抛出异常 - 若你的
useFetch内部支持取消请求,可在useEffect的清理函数中添加批量取消请求的逻辑,避免组件卸载后触发状态更新警告
内容的提问来源于stack exchange,提问作者edche
相关产品推荐
相关产品推荐

