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

ReactJS访问嵌套对象问题:无法获取CoinMarketCap API指定字段

解决CoinMarketCap v2接口数据访问undefined的问题

我帮你梳理下几个关键问题,这些问题导致你无法正确获取total_market_cap和total_volume_24h:


1. 接口数据结构嵌套问题

CoinMarketCap v2的/global接口返回的数据里,total_market_cap和total_volume_24h并不是直接在根对象下,而是嵌套在quotes.USD层级里。接口返回的核心结构大概是这样:

{
  "data": {
    "active_cryptocurrencies": xxx,
    "active_markets": xxx,
    "quotes": {
      "USD": {
        "total_market_cap": xxx,
        "total_volume_24h": xxx
      }
    }
  }
}

所以你需要从quotes.USD里去取这两个值,而不是直接从根对象获取。

2. ComponentDidMount里的函数未执行

你在componentDidMount里只是写了this.props.fetchOverviewData,但没有调用这个函数,应该加上括号执行:this.props.fetch()(注意你的mapDispatchToProps里命名的是fetch,不是fetchOverviewData)。

3. mapDispatchToProps写法错误

当前你的mapDispatchToProps直接执行了dispatch(fetchMarketOverviewData()),这会导致组件初始化时就触发action,而且不是以函数的形式提供给props。正确的写法应该是返回一个包含函数的对象,让组件可以按需调用:

const mapDispatchToProps = dispatch => ({
  fetch: () => dispatch(fetchMarketOverviewData())
});

4. getDerivedStateFromProps的判断逻辑不严谨

初始状态下overview是{}(你设置的defaultProps),不是undefined,所以nextProps.overview === undefined永远不会成立,导致isLoading一直为true(除非你的redux状态直接把overview设为undefined)。应该判断overview是否有有效数据:

static getDerivedStateFromProps(nextProps, prevState) {
  if (!nextProps.overview || !Object.keys(nextProps.overview).length) return null;
  return { isLoading: false };
}

5. Render里的Formatter未传入正确值

你现在的formatter.format()是空的,需要传入对应的USD市场数据,同时还要处理数据可能为undefined的情况,避免报错:

formatter.format(quotes?.USD?.total_market_cap || 0)

修正后的完整代码

import React, { Component } from "react";
import { render } from "react-dom";
import PropTypes from "prop-types";
import styled from "styled-components";
import { ScaleLoader } from "halogenium";
import styleConstants from "../misc/style_constants.js";
import { connect } from "react-redux";
import { fetchMarketOverviewData } from "../actions/api";

const Wrapper = styled.section`
  color: ${styleConstants.get("Light")};
  margin: 20px 0;
`;

const Table = styled.table`
  width: 100%;
`;

const TableData = styled.td`
  &:nth-child(even) {
    text-align: right;
  }
  padding: 5px;
  border-bottom: #234558 solid 0.1px;
`;

const formatter = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  minimumFractionDigits: 0
});

export class Overview extends Component {
  state = { isLoading: true };

  static propTypes = {
    overview: PropTypes.object,
    fetch: PropTypes.func.isRequired
  };

  static defaultProps = {
    overview: {}
  };

  componentDidMount() {
    // 调用fetch函数触发数据请求
    this.props.fetch();
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    // 判断overview是否有有效数据
    if (!nextProps.overview || Object.keys(nextProps.overview).length === 0) {
      return null;
    }
    return { isLoading: false };
  }

  render() {
    if (this.state.isLoading) {
      return (
        <ScaleLoader
          color={styleConstants.get("Light")}
          size="16px"
          margin="4px"
        />
      );
    } else {
      const {
        active_cryptocurrencies,
        active_markets,
        quotes
      } = this.props.overview;
      // 解构USD数据,处理可能的undefined
      const { total_market_cap = 0, total_volume_24h = 0 } = quotes?.USD || {};

      return (
        <Wrapper>
          <Table>
            <tbody>
              <tr>
                <TableData>Total Market Cap</TableData>
                <TableData>{formatter.format(total_market_cap)}</TableData>
              </tr>
              <tr>
                <TableData>Total 24h Volume</TableData>
                <TableData>{formatter.format(total_volume_24h)}</TableData>
              </tr>
              <tr>
                <TableData>Active Markets</TableData>
                <TableData>{active_markets}</TableData>
              </tr>
              <tr>
                <TableData>Active Currencies</TableData>
                <TableData>{active_cryptocurrencies}</TableData>
              </tr>
            </tbody>
          </Table>
        </Wrapper>
      );
    }
  }
}

const mapStateToProps = state => {
  const { data } = state.api.marketOverviewData;
  return { overview: data || {} }; // 确保overview永远是对象,避免undefined
};

const mapDispatchToProps = dispatch => ({
  fetch: () => dispatch(fetchMarketOverviewData())
});

export default connect(mapStateToProps, mapDispatchToProps)(Overview);

另外,建议你在redux的reducer里处理数据时,确保marketOverviewData.data初始值是{},这样可以避免props.overview变成undefined的情况。

内容的提问来源于stack exchange,提问作者Paul McLoughlin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:13:12