Skip to content
Advertisement

Data fetched and set with setState inside useeffect doesnt appear in console log unless i set a timeout

function Groups() {
  const [gamesD, setGames] = useState([]);
  const notInitialRender = useRef(false);
  useEffect(() => {
    const gamesArray = [];
    const groups = [
      'EURO Grp. A',
      'EURO Grp. B',
      'EURO Grp. C',
      'EURO Grp. D',
      'EURO Grp. E',
      'EURO Grp. F',
    ];
    const instance = axios.create({ baseURL: server });
    for (let i = 0; i < groups.length; i++) {
      const fetchGame = async () => {
        const response = await instance.get(`Euro_events?grp=${groups[i]}`);
        gamesArray.push(response.data);
      };
      fetchGame().then(setGames(gamesArray));
    }
  }, []);
  useEffect(() => {
    if (notInitialRender.current) {
      const timer = setTimeout(() => {
        console.log(gamesD[0][0].eventname);
      }, 100);
      return () => clearTimeout(timer);
    } else {
      notInitialRender.current = true;
    }
  }, [gamesD]);

  function logEventsArray(el) {
    console.log('games');
  }
}

So I am fetching data from my database for each item in the array groups and then I want to map through this data (twice because it’s an array inside an array) in the jsx part of the component. The problem though is that the state is changed “too late” This is my guess because the console log doesn’t show the data that is pushed into the gamesArray unless I put a timeout. The timeout doesn’t work though because then the jsx part doesn’t map through anything. The console.log(games) only shows the data if some code is changed in vs code after the site has rendered.

Any advice?

Advertisement

Answer

Try to use a custom hook to fetch all your games.
You can then use the data once they are all fetched:

const useGetGames = () => {
  const [gamesArray, setGamesArray] = useState([]);
  const [loading, setLoading] = useState(true);

  const groups = [
    'EURO Grp. A',
    'EURO Grp. B',
    'EURO Grp. C',
    'EURO Grp. D',
    'EURO Grp. E',
    'EURO Grp. F',
  ];

  const instance = axios.create({ baseURL: server });

  const fetchGames = () => {
    try {
      for (let i = 0; i < groups.length; i++) {
        const { data } = await instance.get(`Euro_events?grp=${group}`);
        setGamesArray((games) => [...games, ...data]);
      }
    } catch (err) {
      console.log(err);
    }

    setLoading(false);
  };

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

  return { loading, gamesArray };
};

Then retrieve the data using:

const { loading, gamesArray } = useGetGames()

if (!loading) {
    // All data should be available
    console.log(gamesArray)
}
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement