Markwin
Markwin

Reputation: 187

React useEffect() state isn't updated

when Im using the useEffect hook with the setState hook, the state isn't updated if I only want the useEffect to run once (i.e. pass an empty array as the second parameter).

If i pass the array that Im updating as the second parameter, the state gets updated but then the useEffect keeps running in an infinite loop...

Here is the code that Im trying to run: In this example when printing out memes or endPage - they still hold their initial state values ([] and 0)

function ImageContainer() {
  const [memes, setMemes] = useState([]);
  const [currentIndex, setIndex] = useState(0);
  const [currentPage, setPage] = useState(1);
  const [endPage, setEndPage] = useState(0);

  useEffect(() => {
    getMemes(currentPage).then((data) => {
      setEndPage(data.pagination.totalPages);
      setMemes(data.data);
      console.log(data);
      console.log(memes);
      console.log(endPage);
    });
  }, []);

enter image description here

but if I pass memes as the second parameter:

function ImageContainer() {
  const [memes, setMemes] = useState([]);
  const [currentIndex, setIndex] = useState(0);
  const [currentPage, setPage] = useState(1);
  const [endPage, setEndPage] = useState(0);

  useEffect(() => {
    getMemes(currentPage).then((data) => {
      setEndPage(data.pagination.totalPages);
      setMemes(data.data);
      console.log(data);
      console.log(memes);
      console.log(endPage);
    });
  }, [memes]);

Then the console.log shows that both of the states have been updated, but the code keeps looping infinitely.

enter image description here

Thanks!

Upvotes: 0

Views: 357

Answers (3)

Luca Fang
Luca Fang

Reputation: 66

It get stacked in infinite loop because the closure you passed to the function then set the state of memes, that trigger the useEffect hook, because it's listening the state of the property memes. You can pass currentPage in the array. Try using a loading state.

Upvotes: 0

HMR
HMR

Reputation: 39320

You needlessly create an infinite loop by adding memes to the effect dependency, log it in the component function instead:

useEffect(() => {
  getMemes(currentPage).then((data) => {
    setEndPage(data.pagination.totalPages);
    setMemes(data.data);
    console.log('api data:',data);
  });
}, []);
console.log('memes:',memes);
console.log('end page:',endPage);

Upvotes: 0

Befeepilf
Befeepilf

Reputation: 647

Your state will get updated but the issue here is that you are checking for state updates by calling console.log(memes) directly after setMemes(data.data), but the state of a component is updated asynchronously which means setMemes is an asynchronous function.

If you want to do something with memes (except updating it) after it has been updated use another useEffect hook and define memes as its dependency.

The infinite loop is happening because you are defining memes as dependency of the useEffect and also updating memes inside the same effect. Therefore this useEffect is constantly triggering itself.

Upvotes: 1

Related Questions