I have 2 question. First, why this code does not work. Second, why this code slow when it comes 2^n -1 for example 1-3-7-15
let time = 0
function App() {
const [mytime, setMytime] = useState(time)
setInterval(() => {
time += 1
setMytime(time)
}, 1000)
return <div> {mytime} </div>
I have 2 question. First, why this code does not work. Second, why this code slow when it comes 2^n -1 for example 1-3-7-15
let time = 0
function App() {
const [mytime, setMytime] = useState(time)
setInterval(() => {
time += 1
setMytime(time)
}, 1000)
return <div> {mytime} </div>
Share
Improve this question
asked Feb 18, 2022 at 11:20
PYigitPYigit
1701 gold badge2 silver badges8 bronze badges
2 Answers
Reset to default 14Issue
The setInterval
gets called each time when mytime
changes for rerendering (when you call the setMytime
). And the number of setInterval
calls grows exponentially. This would lead to a memory leak as well.
Solution
You should run it only once. You should use useEffect
hook with an empty dependency array.
Try like this.
import { useEffect, useState } from "react";
function App() {
const [mytime, setMytime] = useState(0);
useEffect(() => {
// create a interval and get the id
const myInterval = setInterval(() => {
setMytime((prevTime) => prevTime + 1);
}, 1000);
// clear out the interval using the id when unmounting the component
return () => clearInterval(myInterval);
}, []);
return <div> {mytime} </div>;
}
export default App;
To extend @Amila's answer,
What if you want to start
, stop
, reset
timer using functions
?
- Make sure you use
useRef()
, becauseuseState()
will cause render. - Make sure you unmount the interval in the
useState()
as it will cause skipping of timer.useEffect(() => { return () => clearInterval(currentTimer.current); }, []);
Use the following code:
const [time, setTime] = useState(0);
const currentTimer = useRef();
useEffect(() => {
return () => clearInterval(currentTimer.current);
}, []);
const startTimer = () => {
currentTimer.current = setInterval(() => {
setTime((prev) => prev + 1);
console.log(time);
}, 1000);
};
const stopTimer = () => {
clearInterval(currentTimer.current);
};
const resetTimer = () => {
clearInterval(currentTimer.current);
setTime(0);
};
return (
<div>
<div>{time}</div>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
<button onClick={resetTimer}>Reset</button>
</div>
);