skip to Main Content

I have a problem.

there is a need to perform two asynchronous requests. The second is executed with the results of the first. For some reason the data is not being rendered. If I execute only the first request, then the data is rendered. If I add the second, then the data is not displayed.

export const getMatches = async () => {
    const { data } = await axios.get(`https://***/matches`);
    const filteredLive = data.filter((item: TMatches) => item.live);
    console.log(filteredLive, 'filteredLive');
    return filteredLive;
}

    export const getMatchesWithStats = async (matches: TMatches[]) => {
                const matchesWithStats: TMatches[] = [];
            
                matches.map(async (match) => {
                        const { data } = await axios.get(`***/match?id=${match.id}`);
                        match.match = data;
                        matchesWithStats.push(match);
                });
            
                return matchesWithStats;
            }
        
        export const Matches = () => {
        
            const [matches, setMatches] = useState<TMatches[]>([]);
            const [isLoading, setLoading] = useState<boolean>(false);
      
            useEffect(() => {
              
                  const getUseMatch = async () => {
                      const dataMatches = await getMatches();
                      const dataMatchesWithStats = await getMatchesWithStats(dataMatches);
                      setMatches(dataMatchesWithStats);
                  }
                  getUseMatch();
            }, []);
        
            const matchesRendered = matches.map((match) => {
              return (
                <>
                  <StyledTeamName variant="h6">
                    <StyledIconLive>
                      <img src="/live.png" width="32" />
                    </StyledIconLive>
                    &nbsp;
                    {match.team1.name} - {match.team2.name}
                  </StyledTeamName>
                  <StyledTeamNameSubTitle>{match.event.name}</StyledTeamNameSubTitle>
                </>
              );
            });
        
            return <>{isLoading && matchesRendered}</>;
        }

can you help me, please?

3

Answers


  1. this is a common thing you forget as always set array and object states through spreading as react has a shallow copy of the state try :

    setMatches([...dataMatchesWithStats]);
    
    Login or Signup to reply.
  2. getMatchesWithStats internally has an async operation which is never awaited, so it will always return an empty array.

    The callback to .map is async:

    matches.map(async (match) => {
    

    That callback internally awaits its own asynchronous operations, but nothing ever awaits the Promises returned by map(). You can do that with Promise.all. For example:

    await Promise.all(matches.map(async (match) => {
      //...
    }));
    
    return matchesWithStats;
    
    Login or Signup to reply.
  3. The promises created within the map method callback are not being awaited so the array is returned and the state is set before it has any elements. Modifying arrays asynchronously is error-prone so create an array instead like this:

    export const getMatchesWithStats = (matches: TMatches[]) => {
      const matchesWithStats = matches.map(async (match) => {
        const { data } = await axios.get(`***/match?id=${match.id}`);
        return { ...match, match: data };
      });
    
      return Promise.all(matchesWithStats);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search