React中多并发Axios请求问题:无法读取data属性
解决方案
1. 解决"Cannot read properties of undefined (reading 'data')"报错
这个问题核心是部分API请求失败,响应数组中存在未成功的结果,直接访问.data会触发undefined报错。
修复方案:
用Promise.allSettled替代Promise.all,它会保留所有请求的成功/失败状态,再筛选出符合要求的有效响应:
const fetchBlockchainData = async () => { const apiUrls = [ `https://api.bscscan.com/api?module=account&action=tokentx&contractaddress=${tokenContract}&address=${erc20Address}&apikey=YOUR_KEY`, `https://api.etherscan.io/api?module=account&action=tokentx&contractaddress=${tokenContract}&address=${erc20Address}&apikey=YOUR_KEY` // 其他区块链API地址 ]; // 发送所有请求,保留每个请求的状态 const allResults = await Promise.allSettled(apiUrls.map(url => axios.get(url))); // 筛选:仅保留成功请求,且返回message为"OK"的响应数据 const validData = allResults .filter(result => result.status === 'fulfilled') .map(result => result.value?.data) // 用可选链避免意外报错 .filter(data => data?.message === 'OK'); setAnswerAPI(validData); };
2. 解决useEffect中无法访问answerAPI数据的问题
原因是React状态更新是异步的,初始渲染或请求未完成时answerAPI是空数组,直接访问answerAPI[0].data会报错。
修复方案:
在useEffect中先判断数据是否存在,再执行后续逻辑:
useEffect(() => { // 确保数组有数据再处理 if (answerAPI.length === 0) return; // 这里可安全访问answerAPI[0].data console.log(answerAPI[0].data); }, [answerAPI]); // 依赖answerAPI,确保数据更新后触发
3. 解决循环处理引发的无限循环问题
无限循环通常是useEffect的依赖项和内部状态更新形成闭环,比如在useEffect里修改了某个状态,而该状态又在依赖数组中,导致反复触发。
修复方案:
- 拆分逻辑:将"触发请求"和"计算总量"拆分为两个独立的useEffect,避免互相干扰
- 严格控制依赖项:只依赖必要的触发条件(用户输入的地址)
示例:
// 第一个useEffect:用户输入有效时触发API请求 useEffect(() => { // 只有两个输入都不为空时才发起请求 if (!tokenContract || !erc20Address) return; fetchBlockchainData(); }, [tokenContract, erc20Address]); // 仅依赖用户输入,避免无意义触发 // 第二个useEffect:API返回有效数据时计算总量 useEffect(() => { if (answerAPI.length === 0) return; // 计算接收的代币总量(根据API返回的交易结构调整逻辑) const total = answerAPI.reduce((sum, response) => { return sum + response.result.reduce((txSum, tx) => { // 注意:API返回的value通常是wei单位,需要转成代币小数位(比如18位) return txSum + Number(tx.value) / 10 ** 18; }, 0); }, 0); setTotalAmount(total); }, [answerAPI]); // 仅依赖API响应数据,避免循环
额外排查点
- 检查浏览器Network面板,确认所有API请求是否正常返回,有没有跨域或4xx/5xx错误
- 验证API返回的结构是否一致,部分区块链浏览器API可能返回字段名不同(比如有的用
status而非message) - 给axios请求添加错误捕获,避免单个请求的异常影响整个流程:
// 在fetchBlockchainData的map中添加catch apiUrls.map(url => axios.get(url).catch(err => console.error(`请求${url}失败:`, err)))
内容的提问来源于stack exchange,提问作者Charly
相关产品推荐
相关产品推荐

