1

Hello I would like to put setInterval in my React project to add 1 for each second but I got an error like in title of this post. js:

const [activeTab, setActiveTab] = useState(0) useEffect(() => { setInterval(setActiveTab(prevTab => { if (prevTab === 3) return 0 console.log('hi') return prevTab += 1 }), 1000) }) 
1
  • 1
    you should consider the other answer. The answer you selected is not good enough. Commented Jan 23, 2022 at 14:43

2 Answers 2

6

There are a few issues:

  1. You're not passing a function to setInterval, you're calling setActiveTab and passing its return value into setInterval.

  2. If you were passing in a function, you'd be adding a new repeated timer every time your componennt ran. See the documentation — useEffect:

    By default, effects run after every completed render...

    And setInterval:

    The setInterval() method... repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.

    (my emphasis)

    Starting a new repeating timer every time your component re-renders creates a lot of repeating timers.

  3. Your component will leave the interval timer running if the component is unmounted. It should stop the interval timer.

To fix it, pass in a function, add a dependency array, and add a cleanup callback to stop the interval:

const [activeTab, setActiveTab] = useState(0); useEffect(() => { const handle = setInterval(() => { // *** A function setActiveTab(prevTab => { if (prevTab === 3) return 0; console.log("?ghi"); return prevTab += 1; }); }, 1000); return () => { // *** Clear the interval on unmount clearInterval(handle); // *** }; // *** }, []); // *** Empty dependency array = only run on mount 

Side note: Assuming you don't need the console.log, that state setter callback function can be simpler by using the remainder operator:

setActiveTab(prevTab => (prevTab + 1) % 3); 
Sign up to request clarification or add additional context in comments.

1 Comment

Super helpful, thanks. I was seeing jerky behavior, it turns out I always had to run clearInterval at the end of the useEffect function even if I was also clearing it in setActiveTab once the count was reached.
0
 useEffect(() => { setInterval(() => { setActiveTab((prevTab) => { if (prevTab !== 3) { return (prevTab += 1); } else { return 0; } // console.log("hi"); }); }, 1000); }, []); 

7 Comments

This might work
Please explain your answer rather than just dumping code. That makes it useful for other people.
Initially you passed setActiveTab in setInterval function on the place where it takes a function (or say callback function) . So I put there a callback function inside which setActiveTab is going on
for safety measure always put an array as second argument of useEffect useEffect(()=>{}, [])
You should just edit your answer instead of putting it in the comments.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.