Home > Enterprise >  Run setInterval on first render gives maximum update depth exceeded error
Run setInterval on first render gives maximum update depth exceeded error

Time:12-03

In the code snippet below, I add a random number to an array every 3 seconds using setInterval. This goes well, until I try to also call the function on the first render (see the commented line). This gives me this error: Maximum update depth exceeded.

const [listItems, setListItems] = useState([]);

useEffect(() => {
    function extendTheList() {
      const randNr = Math.floor(Math.random() * 10);
      setListItems([...listItems, randNr]);
    }

    // extendTheList();

    const int = setInterval(() => {
      extendTheList();
    }, 3000);
    return () => clearInterval(int);
  }, [listItems]);

Sandbox: https://codesandbox.io/s/vigilant-shamir-ltkh6m?file=/src/App.js

CodePudding user response:

Remove the dependency to avoid infinite loop

const [listItems, setListItems] = useState([]);

useEffect(() => {
    function extendTheList() {
      const randNr = Math.floor(Math.random() * 10);
      setListItems(listItems => [...listItems, randNr]);
    }

    extendTheList();

    const int = setInterval(() => {
      extendTheList();
    }, 3000);
    return () => clearInterval(int);
  }, []);

https://codesandbox.io/s/goofy-stallman-e1m4wo

CodePudding user response:

You have listItems in the dependency array of useEffect which will retrigger the useEffect every time you change listItems.

If you want to use the old value of the state use the function version of setState

const [listItems, setListItems] = useState([]);

useEffect(() => {
  function extendTheList() {
    const randNr = Math.floor(Math.random() * 10);
    setListItems((currentItems) => [...currentItems, randNr]);
  }

  // extendTheList();

  const int = setInterval(() => {
    extendTheList();
  }, 3000);
  return () => clearInterval(int);
}, [setListItems]);

CodePudding user response:

First, you can move the declaration of extendTheList() outside of the useEffect hook. This will ensure that extendTheList() is only called once on the first render, instead of every time listItems is updated.

const [listItems, setListItems] = useState([]);

function extendTheList() {
  const randNr = Math.floor(Math.random() * 10);
  setListItems([...listItems, randNr]);
}

useEffect(() => {
    extendTheList();

    const int = setInterval(() => {
      extendTheList();
    }, 3000);
    return () => clearInterval(int);
  }, []);

This code will call extendTheList() on the first render, and then set up an interval to call it every 3 seconds after that. Because the useEffect hook depends on an empty array, it will only be called once. This should avoid the "Maximum update depth exceeded" error.

  • Related