Photo by Veri Ivanova on Unsplash

Timers created with setTimeout or setInterval are used often in React apps.

setTimeout lets us run code after a delay.

And setInterval lets us run code periodically.

To free up resources and to stop the timers from running, we should call clearTimeout to stop any timers created with setTimeout from running.

Likewise, we should call clearInterval to stop any timers created with setInterval from running.

In this article, we’ll look at the right way to clear timers created with these functions in React components created with hooks.

Clear Timers Created with setTimeout

To clear timers that are created with setTimeout , we should call clearTimeout in the useEffect callback is the function that’s run when the component unmounts.

The function that we return in the useEffect callback is run when the component unmounts, so we should put it there,.

For instance, we can write:

import React, { useEffect, useState } from "react";
export default function App() {
const [loading, setLoading] = useState(true);
  useEffect(() => {
const timer = setTimeout(() => setLoading(false), 1000);
    return () => {
clearTimeout(timer);
};
}, []);
  return <div>{loading ? "loading" : "hello"}</div>;
}

We have the loading state which is initially set to true .

Then we call useEffect with a callback.

In the callback, we call setTimeout with a callback that calls setLoading with false to set loading to false .

And the callback is run after 1000 milliseconds since the 2nd argument is 1000.

Also, we return a function that calls clearTimeout with timer to clear the timer.

This function is run when we unmount the component.

Then we display text according to the value of loading .

So we should see ‘loading’ first. Then we should see ‘hello’ about 1 second later.

Clear Timers Created with setInterval

Likewise, we can clear a timer created with setInterval the same way.

For instance, we can write:

import React, { useEffect, useState } from "react";
export default function App() {
const [time, setTime] = useState(0);
  useEffect(() => {
const timer = setInterval(() => setTime((t) => t + 1), 1000);
    return () => {
clearInterval(timer);
};
}, []);
  return <div>{time}</div>;
}

Almost everything is the same except we replaced setTimeout and clearTimeout with setInterval and clearInterval .

Timers Outside the useEffect Callback

We cal also place timers outside the useEffect callback.

For instance, we can write:

import React, { useEffect, useRef, useState } from "react";
export default function App() {
const [time, setTime] = useState(0);
const timer = useRef();
  useEffect(() => {
timer.current = setInterval(() => setTime((t) => t + 1), 1000);
}, []);
  useEffect(() => {
return () => {
clearInterval(timer.current);
};
}, []);
  return <div>{time}</div>;
}

We create the timer ref with the useRef hook.

Then we set timer.current to the timer returned by setInterval .

Then we can call clearInterval anywhere in our component code.

The same also applies to setTimeout and clearTimeout .

Conclusion

We can store our timers in a ref or a variable in the useEffect callback so we can clear them when we no longer need them.

More content at plainenglish.io


How to Clear Timeout and Interval Timers with React Hooks? was originally published in JavaScript in Plain English on Medium, where people are continuing the conversation by highlighting and responding to this story.