在 React 中设置倒数计时器

Irakli Tchigladze 2022年5月18日
在 React 中设置倒数计时器

在 React 中构建的现代 Web 应用程序通常涉及跟踪时间。例如,如果你有一个博客,则每篇文章都必须显示其日期以及自发布以来经过了多长时间。

React 应用程序可以具有多种功能。在 JavaScript 中实现倒数计时器可能非常困难。它涉及操作日期值或格式化它们。

让我们看一下 React 应用程序中倒计时的示例实现。

React 中倒数计时器的实现

一般来说,所有 React 框架中的倒数计时器都是以相同的方式构建的。组件是 React 应用程序的主要构建块。

在本例中,我们将为倒数计时器构建一个功能组件。我们将使用钩子来维护状态和管理副作用。

在 React 中使用 useState()useEffect() 钩子设置倒数计时器

函数式 React 组件可以有不同的结构,但它们都遵循相同的基本模式。让我们设置一个函数并将其命名为 Countdown

大概,你将在父组件中使用该组件,因此我们也应该接受 props

export default function Countdown(props){
    return (
    <div>
    {!(mins && secs) ? "" : (
        <p>
          {" "}
          {mins}:{secs < 10 ? `0${secs}` : secs}
        </p>
      )}    
    </div>
    )
}

到目前为止,这非常简单。我们将从 props 中获取起始分钟和秒值。如果没有分钟和秒可以倒计时,则没有计时器可以显示空字符串。

如果值可用,最好始终以两位数显示秒数以保持格式一致性,即使它是个位数。我们通过在花括号中使用模板文字来实现这一点。

正如我们所见,minssecs 值已被解构,因此我们的下一步将是这样做。我们还提到我们将需要 useState()useEffect() 挂钩。前者对于跟踪不断变化的时代是必要的。

如果我们使用类组件,我们将使用生命周期方法来处理时间的变化。我们可以将 useEffect() 钩子用于具有许多生命周期方法特性的功能组件。

因此,事不宜迟,让我们将钩子引入我们的应用程序:

import React from "react";
import { useState, useEffect } from "react";
export default function Countdown(props){
  const { startingMinutes = 0, startingSeconds = 0 } = props;
  const [mins, setMinutes] = useState(startingMinutes);
  const [secs, setSeconds] = useState(startingSeconds);
    return (
    <div>
    {!(mins && secs) ? "" : (
        <p>
          {" "}
          {mins}:{secs < 10 ? `0${secs}` : secs}
        </p>
      )}    
    </div>
    )
}

我们必须开始从核心库中导入 useStateuseEffect 钩子。

到目前为止,minssecs 状态变量设置为 0,因此我们不会在屏幕上看到任何内容。但是,如果你更改 propsstartingMinutesstartingSeconds 值,你将看到倒计时的起点。在上面的代码中,我们还定义了更新状态的函数。

倒计时的本质是周期性地扣除一定的时间值。为此,我们将需要 setInterval() 方法。它每隔指定的时间执行一段代码。

在这种情况下,每经过一秒,我们必须将总秒数减少 1。每 60 秒一次,我们还必须将起始分钟数减少 1。

我们完成的应用程序将如下所示:

import React from "react";
import { useState, useEffect } from "react";

export default function Countdown(props) {
  const { startingMinutes = 111, startingSeconds = 0 } = props;
  const [mins, setMinutes] = useState(startingMinutes);
  const [secs, setSeconds] = useState(startingSeconds);
  useEffect(() => {
    let sampleInterval = setInterval(() => {
      if (secs > 0) {
        setSeconds(secs - 1);
      }
      if (secs === 0) {
        if (mins === 0) {
          clearInterval(sampleInterval);
        } else {
          setMinutes(mins - 1);
          setSeconds(59);
        }
      }
    }, 1000);
    return () => {
      clearInterval(sampleInterval);
    };
  });

  return (
    <div>
      {!(mins && secs) ? "" : (
        <p>
          {" "}
          {mins}:{secs < 10 ? `0${secs}` : secs}
        </p>
      )}
    </div>
  );
}

这里有很多东西要解开。首先,让我们解释一下 setInterval() 回调的逻辑,因为这是每隔指定时间执行一次的代码。

首先,我们检查 secs 状态值是否大于 0,如果是,我们使用 secs - 1 值更新状态。这实际上是我们倒计时的核心功能。

下一步定义如果 secsmins 为 0 会发生什么。在这种情况下,我们通过调用 clearInterval() 函数取消代码的重复执行。

最后,在 else 语句中,我们处理秒数达到 0 但仍有分钟数要扣除的情况。

回调函数是第一个参数。它包含应该重复执行的一段代码。

在我们的示例中,我们编写了一个内联函数,但我们也可以很容易地单独编写它并在我们的 setInterval() 方法中引用它,如下所示:

setInterval(someFunction, 1000)

该示例中的第二个参数以及原始示例中的第二个参数是指延迟。它指定 setInterval() 函数应在代码执行之间等待多长时间。

时间值以毫秒为单位指定。在我们的示例中,我们希望倒数计时器每秒执行一次,即 1000 毫秒。

最后,useEffect() 钩子的返回值通常用于清理订阅和取消像 setInterval() 之类的重复函数。在我们的示例中,我们正是这样做的,并在执行我们的 sampleInterval() 回调函数时调用 clearInterval()

Irakli Tchigladze avatar Irakli Tchigladze avatar

Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.

LinkedIn