Reputation: 881
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)
})
Upvotes: 1
Views: 2623
Reputation: 91
useEffect(() => {
setInterval(() => {
setActiveTab((prevTab) => {
if (prevTab !== 3) {
return (prevTab += 1);
} else {
return 0;
} // console.log("hi");
});
}, 1000);
}, []);
Upvotes: 0
Reputation: 1074148
There are a few issues:
You're not passing a function to setInterval
, you're calling setActiveTab
and passing its return value into setInterval
.
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.
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);
Upvotes: 6