'Render Cards after fetch data from api and create an object

I'm trying to learn ReactJS.. Today I was trying to create an array of objects with fetch results and after that create the cards, but I just can update the state but the cards are not re-render.. can you help me?

App.js

  const teamsForLoop = [
    Team1,
    Team2,
    Team3
  ];

  const [allPlayers, setAllPlayers] = useState([]);
  const [team, setTeam] = useState([]);
  const [allTeams] = useState(teamsForLoop);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const playerInfo = async() => {
      setLoading(true)
      allTeams.map(async(teamArray) => {
        setTeam([])
        teamArray.map(async (player) => {
          let playerName = player.split(" ");
          const result = await axios.get(
            `https://www.thesportsdb.com/api/v1/json/2/searchplayers.php?p=${playerName[0]}%20${playerName[1]}`
          );
          if (result.data.player === null) {
            setTeam((state) => {
              return [...state];
            });
          } else {
            setTeam((state) => {
              return [...state, result.data.player[0]];
            });
          }
        });
       setAllPlayers(team);
      });
      setLoading(false);
    };
    playerInfo();
  },[]);

  if (loading) return "...Loading...";

  return (
    <>
      <PlayerList allPlayers={allPlayers} />
    </>
  );
}

export default App;

PlayerList.js

function PlayerList({ allPlayers }) {
  const myData = []
  .concat(allPlayers)
  .sort((a, b) => (a.idTeam !== b.idTeam ? 1 : -1))
  return (
    <div>
      {myData.map((player,index) =>
        (
          <div key={index}>       
            ...........
            </div>
        )
      )}
    </div>
  );
}

I think my problem was on the useEffect hook or maybe on my fetch function.. I already have done it using just arrays but without state.



Solution 1:[1]

Issue

The issue I see now is that you are attempting to cache the fetched players in the team state in the loops and then use the team state to update the players state. The problem here is that React state updates are asynchronously processed, so team hasn't updated when setAllPlayers(team); is called.

Solution

It would be simpler to map the allTeams arrays to the GET requests, wait for them to resolve, and enqueue a single allPlayers state update. Flatten the arrays of team's players and map these to the axios GET Promise. Wait for these to resolve and map the results to the array of players.

Example:

function App() {
  const [allPlayers, setAllPlayers] = useState([]);
  const [allTeams] = useState(teamsForLoop);
  const [loading, setLoading] = useState(true);

  const playerInfo = async () => {
    setLoading(true);
    const response = await Promise.all(
      allTeams
        .flat()
        .map((player) =>
          axios.get(
            `https://www.thesportsdb.com/api/v1/json/2/searchplayers.php?p=${player}`
          )
        )
    );
    const players = response.map((result) => result.data.player[0]);
    setAllPlayers(players);
    setLoading(false);
  };

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

  if (loading) return "...Loading...";

  return <PlayerList allPlayers={allPlayers} />;
}

Edit render-cards-after-fetch-data-from-api-and-create-an-object

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Drew Reese