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

使用React useEffect Hook获取API数据时遇状态为空问题

问题排查与修复方案

我来帮你拆解几个导致数据无法正常加载的关键问题:

1. 异步时序错误:console.log时机不对

你在useEffect里调用getAPI后立刻打印smallData,但getAPI是异步函数——API请求还没完成,React还没来得及更新状态,所以此时打印的是初始的空对象。

解决办法:

  • 要么把smallData加入useEffect的依赖数组,状态更新后自动触发打印:
    useEffect(() => {
      getAPI();
    }, []);
    
    useEffect(() => {
      console.log(smallData); // 状态更新后会触发这里的打印
    }, [smallData]);
    
  • 或者在setSmallData的回调里打印(React 18+支持):
    setSmallData(data, () => console.log(smallData));
    

2. API URL转义字符错误

你的请求URL里用了&,这是HTML的转义字符,在JS里应该直接用&,不然实际请求的URL会是无效的,根本拿不到数据。

修正后的URL:

`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false`

3. 状态结构嵌套冗余

你用setSmallData({data})把API返回的数组包成了{data: [数组]}的结构,导致子组件接收的coin是个嵌套对象,要是子组件想直接取加密货币数据,会找不到对应字段。

正确做法:直接把返回的数组赋值给状态:

setSmallData(data);

4. 异步写法不规范(可选优化)

你同时用了async/await和.then,虽然语法合法,但可读性差。建议统一写法,比如全用async/await并增加错误捕获:

async function getAPI(){
  try {
    const response = await fetch('修正后的URL');
    const data = await response.json();
    setSmallData(data);
  } catch (error) {
    console.error('API请求失败:', error); // 新增错误捕获,方便排查问题
  }
}

5. 子组件数据传递优化(可选)

目前你给每个SmallBox都传整个smallData数组,其实可以在父组件里提前筛选出对应币种的数据再传递,减少子组件的处理逻辑:

<SmallBox className="bitcoin" coin={smallData.find(item => item.id === 'bitcoin')}/>
<SmallBox className="ethereum" coin={smallData.find(item => item.id === 'ethereum')}/>

完整修正后的代码

import React, {useState, useEffect} from 'react';
import SmallBox from './SmallBox';
import './App.css';

function App() {
  const [smallData, setSmallData] = useState([]) // 初始值设为空数组更合理

  async function getAPI(){
    try {
      // 修正URL的转义字符
      const response = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false`);
      const data = await response.json();
      setSmallData(data); // 直接赋值数组
    } catch (error) {
      console.error('获取加密货币数据失败:', error);
    }
  }

  useEffect(() => {
    getAPI();
  }, []);

  // 监听状态变化,打印更新后的数据
  useEffect(() => {
    console.log('更新后的smallData:', smallData);
  }, [smallData]);

  return (
    <div className="app">
      <SmallBox className="balance"/>
      {/* 提前筛选对应币种的数据传递给子组件,加?.避免初始空数组报错 */}
      <SmallBox className="bitcoin" coin={smallData.find(item => item?.id === 'bitcoin')}/>
      <SmallBox className="ethereum" coin={smallData.find(item => item?.id === 'ethereum')}/>
      <SmallBox className="ripple" coin={smallData.find(item => item?.id === 'ripple')}/>
      <SmallBox className="tether" coin={smallData.find(item => item?.id === 'tether')}/>
    </div>
  );
}

export default App;

内容的提问来源于stack exchange,提问作者Owen Osagiede

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:39:45