React组件useEffect调用API时coins变量未拼接进URL的问题咨询
问题原因
- 最核心的问题是
useEffect的依赖数组为空,只会在组件首次挂载时执行1次。如果此时父组件传递的props.coins还未加载完成(是空数组),遍历生成的groups就是空对象,Object.keys(groups).join(",")得到的coins自然是空字符串,不会拼入请求链接。 groups的生成逻辑写在组件顶层,仅会在每次组件重渲染时执行,但空依赖的useEffect只会读取首次挂载时的groups闭包值,后续props.coins更新后也不会重新触发请求。- 额外问题:你在请求完成后把数据存入了
coinInfo状态,但渲染列表时用的是每次重渲染都会被重置为空的普通变量coinData,就算请求成功页面也不会展示对应数据。
修复方案
修改点如下:
- 把
groups的生成逻辑移到useEffect内部,确保每次请求前都用最新的props.coins计算要请求的币种 - 给
useEffect添加props.coins作为依赖,只要币种列表更新就重新发起请求 - 渲染列表时改用存在状态里的
coinInfo,不要用临时变量coinData - 增加边界判断,避免无币种时发起无效请求、接口返回异常时JS报错
修复后代码:
import { useState, useEffect } from "react"; import CoinItem from "./CoinItem"; const CoinList = (props) => { const [coinInfo, setCoinInfo] = useState([]); useEffect(() => { const groups = {}; for (let i = 0; i < props.coins.length; i++) { const coinName = props.coins[i].coinName; if (!groups[coinName]) { groups[coinName] = []; } groups[coinName].push(props.coins[i].coinAmount); } const tickers = Object.keys(groups); const coins = tickers.join(","); // 无币种时直接跳过请求 if (!coins) return; const currency = "cad"; const priceDataUrl = `https://api.coingecko.com/api/v3/simple/price?ids=${coins}&vs_currencies=${currency}`; fetch(priceDataUrl) .then((response) => response.json()) .then((data) => { const coinData = []; tickers.forEach((coin) => { coinData.push({ coinName: coin, coinAmount: groups[coin].reduce( (a, b) => parseFloat(a) + parseFloat(b) ), // 加可选链避免接口无对应币种数据时报错 coinPrice: data[coin.toLowerCase()]?.cad || 0, }); }); setCoinInfo(coinData); }); }, [props.coins]); // 添加依赖,props.coins变更时重新执行请求逻辑 return ( <table className="w-full"> <thead> <tr> <th>Coin</th> <th>Amount</th> <th>Price</th> <th>Value</th> </tr> </thead> <tbody> {/* 改用存在状态中的coinInfo渲染 */} { coinInfo.length > 0 && coinInfo.map((coin) => ( <CoinItem key={coin.coinName} coinAmount={coin.coinAmount} coinName={coin.coinName} coinPrice={coin.coinPrice} coinData={coinInfo} /> )) } </tbody> </table> ); }; export default CoinList;
内容的提问来源于stack exchange,提问作者soodaayush
相关产品推荐
相关产品推荐

