如何在 React 中正确处理和提取 JSON API 数据

本文详解如何在 react 中安全获取、解析并结构化展示来自 rest api 的嵌套 json 数据,重点解决状态管理、数据提取与渲染问题。

在 React 应用中处理 JSON 数据(尤其是来自第三方 API 的嵌套响应)时,需兼顾数据获取的异步性、状态更新的响应式特性以及结构化渲染的安全性。你当前的代码存在几个关键问题:直接操作未声明的 datos 数组(非 React state)、未使用 useState 管理状态、未处理加载/错误状态,且 JSON.stringify(datos) 仅用于调试,无法实现结构化展示。

以下是专业、健壮的解决方案:

✅ 正确做法:使用 useState + 解构 + map 渲染

首先,声明一个受控的 state 变量来存储处理后的航班数据:

import { useState, useEffect } from 'react';

function FlightList() {
  const [datos, setDatos] = useState([]); // ✅ 使用 useState 初始化空数组
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url, options);
        if (!response.ok) throw new Error(`HTTP ${response.status}`);

        const json = await response.json();

        // ✅ 安全解构:检查 success 和 data 是否存在
        const { success, data } = json;
        if (!success || !data || typeof data !== 'object') {
          throw new Error('Invalid API response: missing or malformed data');
        }

 

// ✅ 提取每个日期条目中的 origin/destination/price,并转为扁平数组 const dataList = Object.entries(data).map(([date, flight]) => ({ date, // 可选:保留日期作为标识 origin: flight.origin, destination: flight.destination, price: flight.price, })); setDatos(dataList); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchData(); }, []); // ✅ 空依赖数组确保只在挂载时执行 // ✅ 加载与错误状态处理(提升用户体验) if (loading) return Loading flights...; if (error) return Error: {error}; return ( {datos.length === 0 ? (

No flights available.

) : ( datos.map((flight, index) => ( {flight.origin} → {flight.destination}

Price: €{flight.price}

Date: {flight.date} )) )} ); } export default FlightList;

? 关键要点说明

  • 状态必须通过 useState 管理:datos.push(...) 直接修改普通数组不会触发重新渲染;React 只响应 setState 调用。
  • 避免 JSON.stringify() 渲染:它仅用于调试或序列化,不可读、不语义化,且无法交互。
  • 使用 Object.entries() 替代 for...in:更现代、更安全(自动跳过原型链属性),配合 map 返回新数组,符合函数式编程习惯。
  • 添加加载/错误边界:真实项目中必须处理网络异常、空响应、字段缺失等场景。
  • key 推荐使用唯一标识:如 flight.date 比 index 更可靠(避免列表重排时 DOM 复用问题)。

? 常见错误规避

错误写法 风险
datos.push(json)(无 useState) 状态不可追踪,组件不更新
datos.map(...) 但 datos 初始未定义 运行时报错 Cannot read property 'map' of undefined
忽略 .catch() 或未设 loading=false UI 卡在 loading 状态或静默失败
直接访问 json.data['2025-02-08'].origin 若日期键动态变化或不存在,会报 undefined.origin 错误

掌握这套模式后,你不仅能精准提取 origin/destination/price,还能轻松扩展为显示航班号、航司图标、倒计时等复杂视图。核心原则始终是:解构前校验、状态靠 setState、渲染前判空、体验靠反馈