Snippet

useTimeout

jsx

JavaScript provides a handy method for executing some code after a specified amount of time: window.setTimeout.

When working with React, however, we can run into some problems if we try to use it as-is.

This hook is a "react-friendly" wrapper around setTimeout. You can use it just like you'd use window.setTimeout, and it'll work as you expect.

jsx

In this example, the first render will happen instantly, with hasTimeElapsed being false. Then, 5 seconds later, it'll re-render with hasTimeElapsed set to true.

Any other renders in the meantime, caused by a parent component, won't affect anything.

You can cancel the timeout by changing the delay property to null:

jsx

In this example, if the user clicks the button before the timeout has expired, the timeout will be canceled, and will never fire.

You can also capture the timeout ID to cancel it imperatively:

jsx

You might be wondering: why is this needed? Can't you just use setTimeout instead?

There are 3 problems with using window.setTimeout in React:

  1. This will break if your application is statically-generated or server-side rendered, since window isn't defined
  2. A new timeout will be scheduled whenever this component renders, instead of only once when the component mounts. If our parent component re-renders 10 times, we'll schedule 10 timeouts.
  3. Our callback function is stale; it won't have access to current values for state and props.

That last issue is tricky, and it requires a very clear mental model of how React and JavaScript work (and how they're a bit incompatible with each other).

Dan Abramov wrote about this discrepancy, and how to overcome it, in a fantastic article about useInterval. The exact same principles apply for useTimeout. If you're keen to develop a deeper understanding of React, I highly recommend checking it out.

Link to this heading
Related snippets

Last Updated:
July 29th, 2021