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

React组件useEffect调用API时coins变量未拼接进URL的问题咨询

问题原因
  • 最核心的问题是useEffect的依赖数组为空,只会在组件首次挂载时执行1次。如果此时父组件传递的props.coins还未加载完成(是空数组),遍历生成的groups就是空对象,Object.keys(groups).join(",")得到的coins自然是空字符串,不会拼入请求链接。
  • groups的生成逻辑写在组件顶层,仅会在每次组件重渲染时执行,但空依赖的useEffect只会读取首次挂载时的groups闭包值,后续props.coins更新后也不会重新触发请求。
  • 额外问题:你在请求完成后把数据存入了coinInfo状态,但渲染列表时用的是每次重渲染都会被重置为空的普通变量coinData,就算请求成功页面也不会展示对应数据。
修复方案

修改点如下:

  1. 把groups的生成逻辑移到useEffect内部,确保每次请求前都用最新的props.coins计算要请求的币种
  2. 给useEffect添加props.coins作为依赖,只要币种列表更新就重新发起请求
  3. 渲染列表时改用存在状态里的coinInfo,不要用临时变量coinData
  4. 增加边界判断,避免无币种时发起无效请求、接口返回异常时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:15:04