Dan Abramov’s blog Overreacted is pure gold and contains a ton of information. Take today’s post “Making setInterval Declarative with React Hooks” for example, in which he explains why setInterval
and Hooks (which should be released in today’s planned React 16.8 release) don’t play that nice together out of the box.
// This won't work … time will always remain 0
function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);
return (
<div>Seconds: {time}</div>
);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
A possible fix is to use a functional updater function in setTime()
, yet Dan’s solution is a useInterval
hook, which in itself is amazing.
import React, { useState, useEffect, useRef } from 'react';
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
});
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
As per usual, Dan goes into detail on why it should be written like this and the advantages it has over setInterval
Instead of writing code to set and clear the interval, I can declare an interval with a particular delay — and our useInterval Hook makes it happen.
It’s posts like these that make me even more excited about Hooks 🙂
Can we use setInterval with hooks without using useEffect? In my project I am trying to start timer counting from 10 to 0 when user click on the button, not when component mounts.