如何使用 React Hooks 创建倒数计时器

介绍

在本教程中,您将创建一个倒数计时器。这个计时器将帮助你学习如何利用 React 钩子来更新状态和管理 React 组件中的副作用。

使用 React 钩子,您可以创建更清晰的代码、组件之间可重用的逻辑以及无需类即可更新状态。

倒数计时器是一个常见的 UI 组件,可以用于多种用途。他们可以向用户传达他们做某事的时间或距离某个事件发生的时间。您将在本教程中倒计时的事件是 DigitalOcean 的HacktoberFest

在本教程结束时,您将拥有一个使用 ReactuseState()useEffect()钩子的功能性且可重用的倒数计时器

完成计时器倒计时到 HacktoberFest

先决条件

在开始本指南之前,您需要具备以下条件:

第 1 步 – 创建一个空项目

在这一步中,您将使用Create React App创建一个新项目然后,您将删除引导项目时安装的示例项目和相关文件。

首先,创建一个新项目。在您的终端中,运行以下脚本以使用以下命令安装新项目create-react-app

  • npx create-react-app react-hooks-counter

项目完成后,切换到目录:

  • cd react-hooks-counter

在新的终端选项卡或窗口中,使用Create React App start script启动项目浏览器将自动刷新更改,因此在您工作时保持此脚本运行:

  • npm start

您将获得一个本地运行的服务器。如果项目没有在浏览器窗口中打开,您可以使用http://localhost:3000/. 如果您从远程服务器运行它,则地址将为.http://your_server_ip:3000

您的浏览器将加载一个简单的 React 应用程序,该应用程序包含在 Create React App 中:

反应模板项目

您将构建一组全新的自定义组件,因此您需要先清除一些样板代码,以便您可以拥有一个空项目。

首先,src/App.js在文本编辑器中打开这是注入页面的根组件。所有组件将从这里开始。您可以App.js如何使用 Create React App 设置 React 项目中找到更多信息

src/App.js使用以下命令打开

  • nano src/App.js

你会看到一个这样的文件:

反应钩计数器/src/App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

删除该行import logo from './logo.svg';然后替换return语句中的所有内容以返回一组空标签:<></>这将为您提供一个不返回任何内容的有效页面。最终代码将如下所示:

反应钩计数器/src/App.js

import React from 'react';
import './App.css';

function App() {
  return <></>;
}

export default App;

保存并退出文本编辑器。

最后,删除徽标,因为您不会在此应用程序中使用它。在您工作时删除未使用的文件以避免混淆是一个很好的做法。

在终端窗口中输入以下命令:

  • rm src/logo.svg

如果您查看浏览器,您将看到一个空白屏幕:

chrome 中的空白屏幕

现在项目已设置,您可以创建您的第一个组件。

第 2 步 — 计算还剩多少时间

在这一步中,您将创建一个函数来计算当前日期和 HacktoberFest 第一天之间的剩余时间。

首先,设置一个名为 的函数calculateTimeLeft

反应钩计数器/src/App.js
const calculateTimeLeft = () => {};

接下来,在函数内部,您将使用 JavaScriptDate对象来查找当前的year.

创建一个名为的变量year该变量设置为 JavaScriptdate方法Date.getFullYear()

calculateTimeLeft函数内添加以下代码

反应钩计数器/src/App.js

const calculateTimeLeft = () => {

let year = new Date().getFullYear();

}

注意:您可以使用 JavaScriptDate对象来处理日期和时间。

Date.getFullYear()方法将获取当前年份。

您现在可以使用此变量来计算当前日期与 HacktoberFest 第一天之间的差异。

calculateTimeLeft函数内部year变量下方,添加一个名为 的新变量differenceDate使用以下代码将其设置为等于一个新对象:

反应钩计数器/src/App.js

const calculateTimeLeft = () => {
let year = new Date().getFullYear();

const difference = +new Date(`10/01/${year}`) - +new Date();
}

+Date对象before是告诉 JavaScript 将对象强制转换为整数的简写,它为您提供对象的 Unix 时间戳,表示为自纪元以来的微秒。

为了保持代码的可重用性,您使用JavaScript 模板文字并添加year变量以及 HacktoberFest 的月份和日期。HacktoberFest 于每年 10 月 1 日开始。当您使用year变量代替硬编码年份时,您将始终拥有当前年份。

现在您计算了倒数计时器到期之前的总毫秒数,您需要将毫秒数转换为更友好和人类可读的内容。

步骤 3 — 格式化为天、小时、分钟和秒

在此步骤中,您将创建一个名为 的空对象timeLeft,使用if语句检查是否有剩余时间,并使用数学和模数 ( %) 运算符计算总小时数、分钟数和秒数最后,您将返回timeLeft.

首先,创建名为的空对象timeLeft,然后在if语句中填充天、小时、分钟和秒

calculateTimeLeft函数内部difference变量下方添加以下代码

反应钩计数器/src/App.js

const calculateTimeLeft = () => {
let year = new Date().getFullYear();
let difference = +new Date(`10/01/${year}`) - +new Date();

let timeLeft = {};

}

现在创建一个if语句来比较difference变量以查看它是否大于0

calculateTimeLeft函数内部timeLeft变量下方添加此代码

反应钩计数器/src/App.js

...
 if (difference > 0) {
    timeLeft = {
      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
      minutes: Math.floor((difference / 1000 / 60) % 60),
      seconds: Math.floor((difference / 1000) % 60)
    };
  }
...

在此代码中,您将天数、小时数、分钟数和秒数向下舍入并去掉余数以获得整数值。然后,您可以比较difference以查看它是否大于0

最后,您需要返回,timeLeft以便您可以在组件的其他地方使用该值。

calculateTimeLeft函数内部if语句下方添加此代码

反应钩计数器/src/App.js

const calculateTimeLeft = () => {
    let year = new Date().getFullYear();
    let difference = +new Date(`10/01/${year}`) - +new Date();
    let timeLeft = {};

    if (difference > 0) {
      timeLeft = {
        days: Math.floor(difference / (1000 * 60 * 60 * 24)),
        hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
        minutes: Math.floor((difference / 1000 / 60) % 60),
        seconds: Math.floor((difference / 1000) % 60)
    };
  }

  return timeLeft;

}

现在您已经创建了一个函数来计算距离 Hacktoberfest 的剩余时间,您可以添加控制和更新计时器的应用程序状态。

第 4 步 – 使用useState更新您的应用程序状态useEffect

使用 React Hooks,您可以向现有功能组件添加状态管理功能,而无需将它们转换为类。

在这一步中,您
将从 React导入
useStateuseEffect钩子来管理此组件中的状态。

App.js文件顶部,在导入语句中添加useStateuseEffect

反应钩计数器/src/App.js

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

这段代码告诉 React,你想使用 React 提供的这些特定的钩子和它们的功能。

为了使倒数计时器工作,您需要连接我们之前编写的剩余时间方法来更新状态:

calculateTimeLeft函数下方添加此代码

反应钩计数器/src/App.js
...

const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());

...

这种 JavaScript 语法称为数组解构

useState方法接受一个参数来设置初始状态,并返回一个包含当前状态的数组和一个设置状态的函数。

timeLeft将携带我们的时间间隔对象,并为我们提供设置状态的方法。在组件加载时,该timeLeft值设置为当前剩余时间值。

接下来,您将使用useEffect钩子来处理组件副作用。

注:一个副作用是什么,影响功能范围之外的东西被执行。

在此解决方案中,您将使用钩子setTimeout内部的方法useEffect当在钩子内部使用时setTimeout,类似的setInterval方法是常见的 React 模式useEffect

大多数异步行为,如setTimeoutReact 中方法,都是使用useEffectuseState钩子的组合定义的

注意:您可以了解更多有关何时以及如何使用方法一样setTimeout,并setInterval在本节阵营文档

useState()函数下方添加此代码

反应钩计数器/src/App.js
...

const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());

useEffect(() => {
  const timer = setTimeout(() => {
    setTimeLeft(calculateTimeLeft());
  }, 1000);
});

...

useEffect是更新剩余时间的内容。默认情况下,React 会在每次渲染后重新调用效果。

每次timeLeft在状态中更新变量时,都会useEffect触发。每次触发时,我们都会设置一个 1 秒(或 1,000 毫秒)的计时器,它将更新该时间过后的剩余时间。

此后,该循环将每秒继续。

为了帮助消除堆栈超时和导致错误的可能性,您还应该clearTimeoutuseEffect钩子中添加该方法

添加一个clearTimeout方法,传入变量timer作为参数:

  useEffect(() => {
    const timer=setTimeout(() => {
      setTimeLeft(calculateTimeLeft());
      setYear(new Date().getFullYear());
    }, 1000);
    // Clear timeout if the component is unmounted
    return () => clearTimeout(timer);
  });

return函数每次运行时都会useEffect运行,timer除了组件的第一次运行,如果组件被卸载,则会清除超时。

现在您的状态已设置为calculateTimeLeft()对象并且正在您的效果挂钩内更新,它可以用于构建您的显示组件。

第 5 步 — 使用 Object.keys

在此步骤中,您将使用Object.keys迭代timeLeft对象并构建显示组件。您将使用显示组件显示 HacktoberFest 开始前的剩余时间。

首先,在useEffect名为钩子下创建一个新变量timerComponents

反应钩计数器/src/App.js
...

useEffect(() => {
  setTimeout(() => {
    setTimeLeft(calculateTimeLeft());
  }, 1000);

const timerComponents = [];
...

在迭代 中的键后timeLeft,您将使用此变量在剩余时间推送一个新的JSX 组件

接下来,用于Object.keys迭代timeLeftcalculateTimeLeft函数返回对象

timerComponents变量中添加以下代码

反应钩计数器/src/App.js
...

const timerComponents = [];

Object.keys(timeLeft).forEach((interval) => {
  if (!timeLeft[interval]) {
    return;
  }

  timerComponents.push(
    <span>
      {timeLeft[interval]} {interval}{" "}
    </span>
  );
});
<^>

...

这里的代码循环遍历timeLeft对象的属性如果计时器间隔的值大于零,则会向timerComponents数组添加一个元素

注意:{" "}代码中的额外部分用于显示剩余时间的间隔在屏幕上显示时不会相互碰撞。

{}允许您使用JavaScript您的JSX内部和""增加的空间。

现在您已准备好在 App componentsreturn语句中添加新的 JSX以显示距离 HacktoberFest 的时间。

步骤 6 — 显示剩余时间

在此步骤中,您将向应用程序组件的return语句中添加多个 JSX 组件您将使用三元运算符来检查是否还有剩余时间或是否是 HacktoberFest 的时间,

要使用timerComponents数组,您需要检查它的长度并返回它或让用户知道计时器已经过去。

在空return语句中添加以下代码

反应钩计数器/src/App.js
...

return (
  <div>
    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
 </div>  
);

...

在 React JSX 组件中,您使用三元运算符代替 JavaScriptif语句。这是因为 JSX 中只允许使用表达式。

timerComponents.length行代码检查timerComponents数组中是否有任何内容,如果有则呈现它,否则呈现Time's up!.

接下来,您将在return语句中添加另外两个 JSX 组件,让用户知道他们正在倒计时:

反应钩计数器/src/App.js
...

return (
  <div>
 <h1>HacktoberFest 2020 Countdown</h1>
    <h2>With React Hooks!</h2>   
    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
  </div>
);
...

要使用当前年份而不是硬编码2020,您可以创建一个新的状态变量并将初始状态设置为new Date().getFullYear();

在第一个useState()变量下方,添加以下代码:

反应钩计数器/src/App.js
...

const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
<^>
const [year] = useState(new Date().getFullYear(););
<^>

...

此方法将像您在calculateTimeLeft函数中使用的那样获取当前年份

然后,您可以2020从您的硬编码中删除h1并将其替换为year

反应钩计数器/src/App.js
...

return (
  <div>
    <h1>HacktoberFest {year}Countdown</h1>
    <h2>With React Hooks!</h2>
    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
  </div>
);
...

这将显示您的状态变量,该变量现在将始终具有当前年份。您完成的项目将如下所示:

完成计时器倒计时到 HacktoberFest

查看此GitHub 存储库以查看完整代码。

结论

在本教程中,您使用useStateuseEffect挂钩构建了一个倒计时 UI 组件来管理和更新您的应用程序状态。

从这里,您可以学习如何设计 React 组件的样式以创建更有吸引力的倒计时 UI。

您还可以在 DigitalOcean 上查看完整的How To Code in React.js系列,以了解有关使用 React 进行开发的更多信息。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁