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
相关产品推荐
相关产品推荐

