You need to enable JavaScript to run this app. React中如何定义正确TypeScript接口并遍历渲染API数据
优惠活动
大模型
产品
解决方案
定价
更多

React中如何定义正确TypeScript接口并遍历渲染API数据

对接CoinGecko趋势API的问题排查与实现

现有代码的核心偏差点

  • 状态类型定义错位:API返回的顶层是单个对象结构(包含coins数组、exchanges数组两个字段),但你在useState中把trending的类型设为了ITrending[](即ITrending对象组成的数组),和实际返回结构完全不符,会导致TS类型校验报错,渲染时也找不到需要遍历的coins数组。
  • axios请求泛型传参错误:axios.get<ITrending[]> 会把响应数据标记为数组类型,同样和实际的单对象响应结构不匹配,失去正确的类型提示。
  • 接口字段不全:对照API返回样本,你定义的IItem内缺少score字段,顶层ITrending缺少exchanges字段,如果后续需要使用这些字段会直接报“属性不存在”的TS错误。

修正后的完整实现

1. 调整接口定义

保留你原本的接口命名,仅补全缺失的API实际返回字段即可:

export interface ITrending {
  coins: IItem[]
  exchanges: []
}

export interface IItem {
  item: {
    id: string;
    name: string;
    symbol: string;
    market_cap_rank: number;
    thumb?: string;
    large?: string
    score: number
  } 
}

2. 修正组件逻辑

把状态类型、请求泛型、渲染逻辑全部和实际结构对齐:

import React, { useEffect, useState } from 'react'
import axios from 'axios'
import { ITrending } from '../interfaces'

const TRENDING = 'https://api.coingecko.com/api/v3/search/trending'

const Home = () => {
  // 状态类型改为单对象/空值,和实际API返回结构对齐
  const [trending, setTrending] = useState<ITrending | null>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const loadData = async () => {
      try {
        // 泛型改为ITrending,和响应结构匹配
        const res = await axios.get<ITrending>(TRENDING)
        setTrending(res.data)
      } catch (err) {
        console.error('趋势数据请求失败', err)
      } finally {
        setLoading(false)
      }
    }
    loadData()
  }, [])

  // 加载中兜底,避免访问空值属性报错
  if (loading) return <div>加载中...</div>
  // 数据为空兜底
  if (!trending?.coins) return <div>暂无趋势数据</div>

  return (
    <div className="trending-wrapper">
      <h3>热门趋势币种</h3>
      {/* 直接遍历顶层响应里的coins数组 */}
      {trending.coins.map((coinEntry) => {
        // 每一项的实际币种信息存在item字段里
        const coinInfo = coinEntry.item
        return (
          <div 
            key={coinInfo.id} 
            style={{ display: 'flex', alignItems: 'center', padding: '12px 0', borderBottom: '1px solid #f0f0f0' }}
          >
            <img src={coinInfo.large} alt={coinInfo.name} style={{ width: 32, height: 32 }} />
            <span style={{ marginLeft: 12 }}>
              {coinInfo.name} ({coinInfo.symbol})
            </span>
            <span style={{ marginLeft: 'auto', color: '#999' }}>
              市值排名:{coinInfo.market_cap_rank}
            </span>
          </div>
        )
      })}
    </div>
  )
}

export default Home

关键实现要点

  • 遍历的数组位置要找对:真正需要渲染的币种列表,是API返回顶层对象下的coins字段,这个字段本身就是数组,不需要额外拆包,直接调用数组的map方法渲染即可。
  • 一定要做空值兜底:请求是异步流程,组件首次渲染时状态还是初始的null值,如果不提前判断数据是否加载完成,直接访问trending.coins.map()会直接触发空对象访问报错。
  • 类型定义跟着API实际结构走:定义接口的时候直接对照返回的JSON结构逐层匹配,不要把嵌套数组当成顶层响应的类型,避免出现类型错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 15:36:01