Home > Software design >  React - Fetch Data from API and map nested JSON
React - Fetch Data from API and map nested JSON

Time:12-16

for a few days now I'm trying to solve the following problem. Of course I have researched and tried several solutions to the error message and unfortunately none of them work. I do not know what I'm doing wrong and would therefore like to ask you about it. :)

Error-Message: "TypeError: Cannot read properties of undefined (reading 'map')"

Code:


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 Later I would like to extract the teams from the JSON file. For example: response.teams.home.name

Thank you in advance for your attention! :) If there is any information missing, please let me know.

Many greetings and thanks

CodePudding user response:

Can you try this?

 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;

CodePudding user response:

You need to understand the structure of your data, if you want to map over it appropriately.

Note: Do not use an array index for the key of an item in a mapping. Each game contains a fixture object with an 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>

  • Related