React - 从 API 获取数据并映射嵌套的 JSON

Posted

技术标签:

【中文标题】React - 从 API 获取数据并映射嵌套的 JSON【英文标题】:React - Fetch Data from API and map nested JSON 【发布时间】:2022-01-18 05:58:51 【问题描述】:

几天来,我正在尝试解决以下问题。当然,我已经研究并尝试了几种错误消息的解决方案,不幸的是它们都不起作用。我不知道我做错了什么,因此想问问你。 :)

错误消息: “TypeError:无法读取未定义的属性(正在读取'map')”

代码:


function App() 
  const [games, setGames] = useState();

  useEffect(() => 
    getGames();

    async function getGames() 
      const response = await fetch(
        "https://v3.football.api-sports.io/fixtures?season=2021&league=78&date=2021-12-04",
        
          method: "GET",
          headers: 
            "x-rapidapi-host": "v3.football.api-sports.io",
            "x-apisports-key": "XXX",
          ,
        
      );

      const data = await response.json();
      setGames(data.parameters);
    
  , []);

  return (
    <div>
      <h1>Games</h1>
      <div className="games">
        games.map((game, index) => (
          <div key=index>
            <h2>game.season</h2>
          </div>
        ))
      </div>
      )
    </div>
  );


export default App;

JSON: JSON GET EXAMPLE 稍后我想从 JSON 文件中提取团队。例如:response.teams.home.name

提前感谢您的关注! :) 如果有任何信息缺失,请告诉我。

问候和感谢

【问题讨论】:

首先,不要公开分享您的私有 API 密钥。你的初始状态是空的,你可以创建一个类似 games && games.map(xxx) 的条件。 我看到“参数”属性是一个对象,所以你不能在那里使用地图功能。如果你执行 setGames(data.response) 那么你可以使用 map 函数将你的状态变成一个列表。 为什么不升级到 React 17+ 并利用函数组件?您已经在使用 useState 挂钩。 现在已经在上述条件下尝试过了,不幸的是它也没有工作。但取而代之的是一条新的错误信息:TypeError: games.map is not a function 还删除了“参数”并使用 setGames(data.response) 进行了尝试。也没有成功。 见下面的my response。你可以直接运行sn -p。只要您提供 API 密钥。 【参考方案1】:

如果您想适当地映射它,您需要了解数据的结构。

注意:不要将数组索引用于映射中项目的key。每个游戏都包含一个fixture 对象和一个id

const API_KEY = prompt('Supply the API key'); // Provide the key first!

const  useEffect, useState  = React;

const apiHost = 'v3.football.api-sports.io';
const apiUrl = `https://$apiHost/fixtures`;
const apiKey = API_KEY;

const toParamString = (obj) => new URLSearchParams(obj).toString();

const getGames = ( season, league, date ) => 
  const url = `$apiUrl?$toParamString( season, league, date )`;
  return fetch(url, 
      method: 'GET',
      headers: 
        'x-rapidapi-host': 'v3.football.api-sports.io',
        'x-apisports-key': apiKey,
      ,
    )
    .then(response => response.json())
    .then(data => data.response);
;

const Score = (props) => 
  const  game:  fixture:  date , score:  fulltime , teams   = props;
  
  return (
    <div className="score">
      <div className="score-date">new Date(date).toLocaleString()</div>
      <div className="score-grid">
        <div>teams.home.name</div>
        <div>teams.away.name</div>
        <div>fulltime.home</div>
        <div>fulltime.away</div>
      </div>
    </div>
  );
;

const App  = () => 
  const [games, setGames] = useState([]);
  
  useEffect(() => 
    getGames(
      season: 2021,
      league: 78,
      date: '2021-12-04'
    ).then(data => setGames(data));
  , []);
    
  return (
    <div>
      <h1 style= textAlign: 'center' >Games</h1>
      <div className="games">
        games.map((game) => 
          const  fixture:  id   = game;
          return (
            <Score key=id game=game />
          );
        )
      </div>
    </div>
  );
;

ReactDOM.render(<App />, document.getElementById('react-app'));
html, body 
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;


body 
  display: flex;
  flex: 1;


#react-app 
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;


.score 
  border: thin solid grey;
  margin: 0.667em;
  padding: 0.33em;


.score-date 
  display: flex;
  justify-content: center;
  font-weight: bold;
  font-size: larger;
  margin-bottom: 0.25em;


.score-grid 
  display: grid;
  grid-template-columns: repeat(2, 1fr);


.score-grid div 
  display: flex;
  justify-content: center;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react-app"></div>

【讨论】:

有效! :) 非常感谢您将如此详细的代码放到网上!这非常有帮助!现在将研究代码以了解它是如何工作的。【参考方案2】:

你可以试试这个吗?

 function App() 
      const [games, setGames] = useState();
    
      useEffect(() => 
        getGames();
    
        async function getGames() 
          const response = await fetch(
            "https://v3.football.api-sports.io/fixtures?season=2021&league=78&date=2021-12-04",
            
              method: "GET",
              headers: 
                "x-rapidapi-host": "v3.football.api-sports.io",
                "x-apisports-key": "3914b827d25c9a793d6af1ec9c312d55",
              ,
            
          );
    
          const data = await response.json();
          setGames(data.parameters);
        
      , []);
    
      return (
        <div>
          <h1>Games</h1>
          <div className="games">
            Object.keys(games).length > 0 && games.map((game, index) => (
              <div key=index>
                <h2>game.season</h2>
              </div>
            ))
          </div>
          )
        </div>
      );
    
    
    export default App;

【讨论】:

'parameters' 键是一个对象,因此您无法通过它进行映射。请添加更多信息来解释您所做的修复。 很遗憾,您的想法也没有奏效:/ 现在出现错误消息:TypeError: games.map is not a function 我一直没有进行任何重大更改。总是尝试并失败 :D 例如,已经尝试一步一步地映射“游戏”以越来越深入。但是,总是出现错误消息。然后我在没有 .map() 的情况下尝试了它并收到以下错误消息:错误:对象作为 React 子项无效(找到:带有键 的对象)。如果您打算渲染一组子项,请改用数组。由此我再次明白我必须通过 .map() 映射“游戏”。从那以后,我一直在兜圈子,找不到更多的解决方案。

以上是关于React - 从 API 获取数据并映射嵌套的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

如何从 JSON 映射嵌套数组?

如何从 React 中的嵌套对象数组中提取数据?

React:迭代深度嵌套的对象并显示它们而不会撕裂我的头发

如何在 React 的 API 中渲染嵌套在对象中的数组中的数据?

在按每个用户ID映射和获取用户详细信息时,API无法正确获取用户的数据

React Context : 从 API 获取数据并在 React 组件中发生某些事件时调用 API