React + TypeScript:将 setTimeout() 与 Hooks 一起使用

这篇简洁实用的文章将向您介绍在使用TypeScript编写的 React 应用程序中使用window.setTimeout() 和window.clearTimeout() 方法的完整示例。我们将使用带有钩子的功能组件(useStateuseEffectuseRef)。你不会看到像类组件、this.setState 或类似的东西这样的老式东西。

简要概述

setTimeout() 方法用于在几毫秒后触发一个函数。它返回一个类型为number的 id。您可以使用此idclearTimeout() 方法来停止由setTimeout() 设置的计时器:

let myTimer: number;

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

// clearTimeout
window.clearTimeout(myTimer);

在上面的代码片段中,您可以注意到我们显式调用了window.setTimeout() 和window.clearTimeout() 。此操作告诉 TypeScript 我们正在为前端 Web 应用程序编写代码。

在现代 React 中,您可以将setTimeout() 与钩子一起使用,如下所示:

// 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);
      }
    };
}, []);

为了更好地理解,请参阅下面的端到端工作示例。

注意:setTimeout() 方法只执行一次。如果您需要重复执行,请改用setInterval()方法

这个例子

应用预览

我们要使用的演示项目有 2 个按钮:

  • 显示:此按钮为绿色。当它被按下时,将设置一个计时器,5 秒后,将出现一个蓝色框。在这 5 秒期间,该按钮被禁用以防止用户与其交互。
  • 取消:一开始,此按钮被禁用。它仅在计时器运行时启用。您可以使用此按钮停止计时器。

下面的动画 GIF 截图清楚地描述了我的意思:

React + TypeScript:将 setTimeout() 与 Hooks 一起使用

编码

  1. 创建一个完全支持 TypeScript 的 React 项目:
npx create-react-app kindacode-example

会生成很多文件和文件夹,但请注意这两个文件:src/App.tsxsrc/App.css

2. 将App.tsx中的所有默认代码替换为以下内容(您可以在评论中找到解释):

// 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. 擦除App.css中所有不需要的 CSS 代码,然后添加以下内容:

/* 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;
}
  1. 最后要做的是启动它并在 http://localhost:3000 检查结果:
npm start

总结

这是一个小而有意义的项目,它使用了window.setTimeout() 方法、React 钩子和 TypeScript。尝试修改代码,进行一些更改,调整一些值,然后看看会发生什么结果。