React + TypeScript: Using setTimeout() with Hooks

Last updated on August 15, 2022 A Goodman Loading... Post a comment

This succinct, practical article walks you through a complete example of using the window.setTimeout() and window.clearTimeout() methods in a React application that is written in TypeScript. We’ll use functional components with hooks (useState, useEffect, and useRef). You won’t see old-fashioned stuff like class components, this.setState, or something like that.

Without any further ado, let’s get started.

A Brief Overview

The setTimeout() method is used to trigger a function after a number of milliseconds. It returns an id whose type is number. You can use this id and the clearTimeout() method to stop the timer set by setTimeout():

let myTimer: number;

// setTimeout
myTimeout = window.setTimeout(() => {/* ...*/}, 3000);

// clearTimeout
window.clearTimeout(myTimer);

In the code snippet above, you can notice that we explicitly called window.setTimeout() and window.clearTimeout(). This action tells TypeScript that we’re writing code for a frontend web app.

In modern React, you can use setTimeout() with hooks like so:

// use ref to store the timer id
const refTimer = useRef<number | null>(null);

// trigger the timer
const startTimer = () => {
    if (refTimer.current !== null) return;
    refTimer.current = window.setTimeout(() => {
       /* do something here */
    }, 5000);
};

// stop the timer
const stopTimer = () => {
    if (refTimer.current === null) return;
    window.clearTimeout(refTimer.current);
    refTimer.current = null;
};

// Cleanup function to clear the timer when the component unmounts
useEffect(() => {
    // cleanup function
    return () => {
      if (refTimer.current !== null) {
        window.clearTimeout(refTimer.current);
      }
    };
}, []);

To gain a better understanding, please see the end-to-end working example below.

Note: The setTimeout() method is executed only once. In case you need repeated executions, use the setInterval() method instead

The Example

App Preview

The demo project we’re going to work with has 2 buttons:

  • Show: This button is green. When it gets pressed, a timer will be set and after 5 seconds, a blue box will show up. During this 5-second period, the button is disabled to prevent the user from interacting with it.
  • Cancel: In the beginning, this button is disabled. It is only enabled while the timer is running. You can use this button to stop the timer.

The animated GIF screenshot below clearly describes what I mean:

The Code

1. Create a totally React project that supports TypeScript:

npx create-react-app kindacode-example

A lot of files and folders will be generated but turn your attention to these 2 files: src/App.tsx and src/App.css.

2. Replace all of the default code in App.tsx with the following (you can find explanations in the comments):

// Kindacode.com
// App.tsx
import React, { useState, useEffect, useRef } from 'react';
import './App.css';

const App = () => {
  // show/hide state of the box
  const [isShown, setIsShown] = useState(false);

  // the timer is set or not
  const [isRunning, setIsRunning] = useState(false);

  // use ref to store the timer id
  const refTimer = useRef<number | null>(null);

  // show the box after 5 seconds
  const showBox = () => {
    if (refTimer.current !== null) return;
    setIsRunning(true);
    refTimer.current = window.setTimeout(() => {
      setIsShown(true);
      setIsRunning(false);
    }, 5000);
  };

  // prevent the box from being shown by clearing the timer
  const stopTimeout = () => {
    if (refTimer.current === null) return;
    window.clearTimeout(refTimer.current);
    refTimer.current = null;
    setIsRunning(false);
  };

  // Cleanup function to clear the timer when the component unmounts
  useEffect(() => {
    // cleanup function
    return () => {
      if (refTimer.current !== null) {
        window.clearTimeout(refTimer.current);
      }
    };
  }, []);

  return (
    <div className='container'>
      <div className='buttons'>
        {/* This button is used to start the timer */}
        <button
          disabled={isRunning || isShown}
          onClick={showBox}
          className='button-show'
        >
          Show
        </button>

        {/* This button is used to cancel the timer */}
        <button
          disabled={!isRunning}
          onClick={stopTimeout}
          className='button-stop'
        >
          Cancel
        </button>
      </div>

      {/* Some useful messages */}
      {!isRunning && !isShown && (
        <p>Click the "Show" button and wait 5 seconds to see the blue box</p>
      )}

      {isRunning && (
        <p>Press the "Cancel" button to prevent the box from shows up</p>
      )}

      {/* The box */}
      {isShown && (
        <div className='box'>
          <h1>Welcome to KindaCode.com</h1>
        </div>
      )}
    </div>
  );
};

export default App;

3. Wipe all unwanted CSS code in your App.css out then add the following:

/* App.css */
.container {
  width: 80%;
  margin: 10px auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* Style the buttons */
.buttons {
  margin-top: 20px;
  display: flex;
  justify-content: center;
}

.button-show {
  margin: 0 10px;
  padding: 10px 20px;
  background: #4caf50;
  color: white;
  border: none;
  cursor: pointer;
}

.button-show:hover {
  background: #43a047;
}

.button-show:disabled {
  background: #ccc;
  cursor: not-allowed;
}

.button-stop {
  margin: 0 10px;
  padding: 10px 20px;
  background: #f44336;
  color: white;
  border: none;
  cursor: pointer;
}

.button-stop:hover {
  background: #e53935;
}

.button-stop:disabled {
  background: #ccc;
  cursor: not-allowed;
}

/* Style the box */
.box {
  margin-top: 50px;
  width: 100%;
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2196f3;
  color: white;
}

4. The last thing to do is to boot it up and check the result at http://localhost:3000:

npm start

Recap

Congratulation! You made it, a small but meaningful project that uses the window.setTimeout() method, React hooks, and TypeScript. Try to modify the code, make some changes, adjust some values, and see and see where that leads you.

If you’d like to explore more new and interesting stuff about modern React, take a look at the following articles:

You can also check our React topic page and Next.js topic page for the latest tutorials and examples.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Related Articles