If you want to "stop" the timer and do something with the current counter
value than I have some suggested tweaks to allow your timer to be paused/stopped and issue a side-effect with the current state.
Modify the useInterval
hook to always run the cleanup function when the dependency updates. You can also simplify the interval callback, i.e. pass the callback ref's current value.
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
let id;
if (delay) {
id = setInterval(savedCallback.current, delay);
}
return () => clearInterval(id);
}, [delay]);
}
Add a delay
state to your component that you can toggle between null
and 1000
.
const [delay, setDelay] = useState(1000);
Use a functional state update in your setCounter
state updater to avoid stale state enclosures.
useInterval(() => setCounter((c) => c + 1), delay);
Add a button to toggle the interval running.
<button
type="button"
onClick={() => setDelay((delay) => (delay ? null : 1000))}
>
{delay ? "Pause" : "Start"}
</button>
Use an useEffect
hook to run a side-effect to do what you need with the counter
state when the interval is paused/stopped
useEffect(() => {
if (delay === null) { /* do stuff */ }
}, [counter, delay]);
Demo
Full code:
function Counter() {
const [counter, setCounter] = useState(0);
const [delay, setDelay] = useState(1000);
useInterval(() => setCounter((c) => c + 1), delay);
useEffect(() => {
if (delay === null) { /* do stuff */ }
}, [counter, delay]);
return (
<div className="App">
<h2>Counter: {counter}</h2>
<button type="button" onClick={() => setCounter(0)}>
Reset
</button>
<button
type="button"
onClick={() => setDelay((delay) => (delay ? null : 1000))}
>
{delay ? "Pause" : "Start"}
</button>
</div>
);
}
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
let id;
if (delay) {
id = setInterval(savedCallback.current, delay);
}
return () => clearInterval(id);
}, [delay]);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…