Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

224
Visualizações
React API calls not fully completing before rendering

I'm essentially brand new to React, so please bear with me if there are any strange or obvious mistakes that I am missing.

I am looking to create a small little project with the National Hockey League statistics API and unfortunately have run into an issue pretty early on.

Essentially, what this code is trying to do right now is to fetch all of the current team ID's through https://statsapi.web.nhl.com/api/v1/teams, and then loop through each team's response and use it's unique ID to store every player ID currently playing in the league https://statsapi.web.nhl.com/api/v1/teams/ID/roster.

The API requests seem to be working just fine, however I'm running into an issue where the check for loading seems to be functioning improperly. If I say, for example

{loading ? <p>Loading...</p> : <p>{playerList[0].jerseyNumber}</p>}

I am given a "Cannot read properties of undefined" error message.

Is the way I attempted to signify loading incorrect? Is there a better way to be certain that the API requests are 100% finished before accessing the data?

Here is my code:

function App() {
    const [playerList, setPlayerList] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect (() => {
        fetch("https://statsapi.web.nhl.com/api/v1/teams")
            .then((teamsResponse) => teamsResponse.json())
            .then((teamsData) => {
                const teams = teamsData.teams;
                teams.forEach((team) => {
                    fetch("https://statsapi.web.nhl.com/api/v1/teams/" + team.id + "/roster")
                        .then((teamResponse) => teamResponse.json())
                        .then((teamData) => {
                            const roster = teamData.roster
                            roster.forEach((player) => {
                                setPlayerList((oldList) => [...oldList, player]);
                            });
                        });
                    });
                });

            setLoading(false);
    }, []);

    return (
        <div>
            {loading ? <p>Loading...</p> : playerList && <p>{playerList[0].jerseyNumber}</p>}
        </div>
    );
}
about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You're calling setLoading(false) outside of the fetch call. That is going to invoke the fetch and call setLoading(false) without waiting for the promise to resolve.

If you want the loading indicator to be set to false only after all of the roster fetch calls then you'll need to use Promise.all with a then. where you set the loading indicator to false, such as:

const teams = teamsData.teams;
const rosterRequests = teams.map(team => {
  fetch("https://statsapi.web.nhl.com/api/v1/teams/" + team.id + "/roster")
    .then(teamResponse => teamResponse.json())
    .then(teamData => {
      // Update roster state
    });

// This will be executed once all the team roster requests have completed
Promise.all(rosterRequests).then(() => setLoading(false));

You can read more about Promise.all here.

about 4 years ago · Juan Pablo Isaza Relatório

0

You are setting loading to false before the data is loaded. Try putting setLoading(false); into

                        .then((teamData) => {
                            const roster = teamData.roster
                            roster.forEach((player) => {
                                setPlayerList((oldList) => [...oldList, player]);
                            });
                            setLoading(false); <---
                        });
about 4 years ago · Juan Pablo Isaza Relatório

0

setLoading should be set to false when all promises are settled since there are nested requests, I have updated and tested the solution

Updated code

useEffect(() => {
    fetch("https://statsapi.web.nhl.com/api/v1/teams")
      .then((teamsResponse) => teamsResponse.json())
      .then((teamsData) => {
        const teams = teamsData.teams;
        let arr = [];

        const allRosterData = teams.map(async (team) => {
          const rosterData = await fetch(
            "https://statsapi.web.nhl.com/api/v1/teams/" + team.id + "/roster"
          )
            .then((teamResponse) => teamResponse.json())
            .then((teamData) => {
              const dt = [];
              const roster = teamData.roster;
              roster.forEach((player) => {
                dt.push(player);
              });

              return dt;
            });

          arr = [...arr, ...rosterData];

          return rosterData;
        });

        Promise.all(allRosterData)
          .then(() => {
            //Change state here when all promises are settled
            setPlayerList(arr);
            setLoading(false);
          })
          .catch((err) => {
            console.error(err);
          });
      });
  }, []);
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda