1

I have a useState variable that I want to update every 5 seconds by an increment of 1, however I want it to stop counting and start at 0 again once it reaches the array's length. Here is what I have so far. Right now the console logs are confusing, it starts to work and then the numbers just start outputting every second or faster. This works when I dont run the SetShowNum in the increment function, but that's the functionaility I need.

Any help would be greatly appreciated. Thanks

const [showNum, SetShowNum] = useState(0)

  useEffect(() => {
    var i = 0

    var interval = setInterval(increment, 5000)

    var stop = data.allSanityProducts.edges.length // right now equates to 4

    function increment() {
      i = i + 1

      if (i === stop) {
        i = 0
      }

      console.log(i)
      SetShowNum(i)
    }
  })
Anders Kitson
  • 1,413
  • 6
  • 38
  • 98
  • Does this answer your question? [setInterval in a React app](https://stackoverflow.com/questions/36299174/setinterval-in-a-react-app). There are some hooks examples. – ggorlen Aug 25 '20 at 23:52
  • You also have to have a clearInterval in the useeffect cleanup – charlietfl Aug 25 '20 at 23:52
  • I was reading about clearinterval in the cleanup but wasn't sure how to accomplish that based on the react docs – Anders Kitson Aug 26 '20 at 00:17

1 Answers1

2

In this solution, I added a dependency array as a second argument for the useEffect. This ensures that useEffect only runs when the component first mounts. Otherwise, the useEffect as you wrote it will keep running on each re-render so that is why you're seeing the memory leakage and all the log statements. I threw in log statements in the useEffect to observe this behavior. I would recommend running the code with and without the dependency array to observe the re-rendering occur.

The React documentation:

"If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works."

const Component = () => {
  console.log("rerender");

  const [showNum, SetShowNum] = useState(0);
  
  useEffect(() => {
    console.log("running useEffect");
    var i = 0;

var interval = setInterval(increment, 5000);

// var stop = data.allSanityProducts.edges.length // right now equates to 4
const stop = 4;

function increment() {
  i = i + 1;

  if (i === stop) {
    i = 0;
  }

  console.log(i);
  SetShowNum(i);
}
  }, []);

  return (...)
};

Link to React useEffect docs: https://reactjs.org/docs/hooks-effect.html

Link to a codesandbox: https://codesandbox.io/s/nameless-sunset-1qyq4?file=/src/SO.js:0-590

Dharman
  • 30,962
  • 25
  • 85
  • 135
CaliTab
  • 156
  • 1
  • 5