Making setInterval Declarative with React Hooks

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 πŸ™‚

Making setInterval Declarative with React Hooks →

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.