useTime() React Hook

Countdowns in React are complicated/hard. Let’s use hooks to create a useTime hook.

James Fulford
Oct 17, 2019 · 3 min read
Time keeps on ticking… Photo by Djim Loic on Unsplash

The Hook (Code First!)

Copy-paste this gist (https://gist.github.com/jamesfulford/7f3311bd918982e68d911a9c70b27415) and give it a try in your codebase. Don’t worry, this article will still be here when you get back.

useTime, getTime, and sample usage in a Countdown component.

This gist currently uses Luxon for handling dates, but the comments show how to convert it to use Moment, or native JS Dates. An epoch integer is also a wise move if timezones are complicated.

PSA: If you’re working with timezones, use a library. Else, this will happen to you and all your friends: (I warned you)

The Problem

Using the current time when rendering a React component can be tricky. The present literature (Medium articles, assorted blogs, and StackOverflow answers) often has 3 problems:

Implementation is Wrong

Working with the current time in React is hard. The common solution of callbacks incrementing/decrementing state will fall out of sync quickly because of a misunderstanding of in Javascript, and because of a misunderstanding of transitions in React.

Directly accessing the current time in the method will not trigger re-renders when needed, and passing through a prop/context only defers the problem to a different component. Therefore, a solution using state is the right solution.

Some implementations available on blogs, Medium articles, and StackOverFlow answers update state incorrectly. Some countdown implementations will store seconds remaining, then will decrement the seconds remaining every 1000ms using . This will fall out of sync with actual-time very quickly, depending on:

  • how long the tab is visible (browsers deprioritize calls for non-focused pages for performance reasons)
  • how complicated the rest of your app is (the thread may not get to the callback quickly enough if there is a lot of work to do)
  • the performance specs of the viewing device (mobile devices will execute JS slower, for example)

If you want to learn more, research the “Javascript Event Loop” — several good interview questions revolve around this concept. This is not specific to React.

Getting React-specific, some implementations do not consider the fact that will not immediately update state. This means the first state update may not have been executed before the second state update was queued. This is a problem if the implementation relies on the previous state to decide the next state, (i.e. time is incremented or decremented), because time will go out of sync (because two duplicate updates were queued).

The solution is either to pass a function to as shown in the React docs, or (better solution) don’t rely on the previous state to get the current state. Inside the callback, update state with the most recent time.

No Clean-Up is Done

In a class component, a method can clean up the interval id using something like . However, some implementations neglect this important detail, potentially causing memory leaks in the code of those who copy the implementation.

My Lifecycle Methods Are Huge (“It’s not a hook”)!

If a React component gets large (maybe you inherited bad code), it can take quite a lot of scrolling to go from the call to the call and the accessing of the current time from . This violates one of my personal rules of thumb:

Things that are related should be close to each other.

Incidentally, this is the motivation for switching to hooks in React.

I have yet to find a hook that does this for consuming and updating the current time. So please, enjoy my implementation.

By the way, this “Things that are related should be close to each other” rule-of-thumb a special case of one of my personal favorite rules (which has life/moral implications if fully adopted):

Make it easy to do the right thing; make it hard to do the wrong thing.

To learn more about this philosophy, check out one of my earlier articles (hey, you read this far!):

JavaScript in Plain English

Learn the web's most important programming language.

James Fulford

Written by

Harvard. Tech Lead. American. jamesfulford.com

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade