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

React渲染fetch对象数组及多组数据存state实现方法

问题根因

所有渲染异常都来自对接口返回的数据结构判断错误:

  • 接口返回的response是餐厅对象构成的数组,不是单个对象,因此直接读取response.meniu会得到undefined——数组类型本身不存在meniu属性
  • 每个餐厅对象下的meniu字段同样是菜品对象构成的数组,不是单个菜品对象,因此直接写user.meniu.pret无法读取到值:数组不存在pret属性。user.meniu[0].pret能正常显示值,刚好印证了meniu是数组类型,[0]是读取数组中第一个菜品的价格。
  • 代码中连续两次调用setMeniu,后一次的赋值会覆盖前一次的结果,最终meniu状态存储的永远是undefined。
  • useState未设置对应类型的初始值,首次渲染时users为undefined,虽然后续加了users &&的判断做拦截,但写法冗余。
正确实现代码
import { useState, useEffect } from 'react';

function App() {
  // 初始值设为空数组,和接口返回类型对齐
  const [users, setUsers] = useState([]);

  const getApiData = async () => {
    const res = await fetch("https://vercelfastfoodapi.vercel.app/fastfood/");
    const data = await res.json();
    // 接口直接返回餐厅数组,直接存入状态即可
    setUsers(data);
  };

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

  return (
    <div className="App">
      {users.map((user) => (
        <div className="item-container" key={user._id}>
          <p>餐厅名称:<b>{user.restaurant}</b></p>
          <p>菜品列表:</p>
          <ul>
            {/* meniu是数组,需要二次遍历才能渲染所有菜品,不能直接取.pret */}
            {user.meniu?.map((dish, idx) => (
              <li key={idx}>
                菜品名:{dish.nume} —— 价格:{dish.pret}
              </li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

export default App;
修正点说明
  • 移除了冗余的meniu全局状态:渲染全量餐厅的所有菜品时,不需要单独提取某一个餐厅的菜品数组存为全局状态,遍历users数组时嵌套遍历每个餐厅对应的meniu数组即可
  • 给useState设置初始值为空数组[],和接口返回的数组类型对齐,不需要额外写users &&的非空判断,减少边界判断代码
  • 访问user.meniu时增加可选链操作符?.,兼容接口返回异常、个别餐厅无菜品数据的边界场景,避免页面白屏报错
  • 对每个餐厅下的meniu数组做二次遍历,即可渲染出该餐厅所有菜品的价格、名称等信息,解决只能显示第一个菜品价格的问题
  • 删除了重复的setMeniu调用,避免后一次赋值覆盖前一次有效值的问题。

如果业务需求确实需要单独存储某一家餐厅的菜品列表(比如索引为1的餐厅),只保留对应赋值语句即可,不要连续两次调用setMeniu造成值覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:54:14