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 →

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Join the Conversation

1 Comment

  1. 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.

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.