如何使用 React 挂钩创建倒计时器

介绍

在本教程中,您将使用 React 挂钩创建一个倒计时器,以更新 React 组件的状态和管理副作用。

使用 React Hooks,您可以创建更清洁的代码,在组件之间创建可重复使用的逻辑,并在没有类的情况下更新状态。

计时计时器是一个常见的用户界面组件. 它们可以向用户传达他们在做某件事多久或多长时间,直到某个事件发生。

到本教程结束时,您将使用 React 的 useState()useEffect() 锁定功能性和可重复使用的 Countdown 计时器。

Screenshot of the completed timer counting down to Hacktoberfest

前提条件

在您开始本指南之前,您将需要以下内容:

要在 macOS 或 Ubuntu 18.04 上安装此功能,请遵循 如何在 macOS 上安装 Node.js 并创建本地开发环境 的步骤如何在 Ubuntu 18.04 上安装 Node.js 使用 PPA 设置项目How To Set Up a React Project with Create React App部分] *在本教程中,您将使用 Create React App创建应用程序。

此教程已通过 Node.js v16.13.1, npm v8.2.0 和 react v17.0.2 进行验证。

步骤 1 – 创建一个空的项目

在此步骤中,您将使用 Create React App创建一个新项目,然后您将删除在启动项目时安装的样本项目和相关文件。

要开始,创建一个新项目. 在终端中,运行以下脚本以使用create-react-app安装新项目:

1npx create-react-app react-hooks-timer

项目完成后,更改到目录:

1cd react-hooks-timer

在新的终端卡或窗口中,使用 Create React App start script启动项目。

1npm start

如果项目未在浏览器窗口中打开,您可以使用http://localhost:3000/打开,如果您正在从远程服务器运行,则地址将是http://your_server_ip:3000

您的浏览器将加载由 Create React App 生成的 React 应用程序:

React template project

您将构建一组新的自定义组件,因此您需要从清除一些锅炉板代码开始,以便您可以有一个空的项目。

要开始,请在文本编辑器中打开src/App.js。 这是注入到页面的根组件。 所有组件将从这里开始。 您可以找到有关App.js的更多信息,请参阅How To Set Up a React Project with Create React App(如何使用Create React App设置反应项目(LINK0))。

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

1nano src/App.js

你會看到這樣的檔案:

 1[label react-hooks-timer/src/App.js]
 2import React from 'react';
 3import logo from './logo.svg';
 4import './App.css';
 5
 6function App() {
 7  return (
 8    <div className="App">
 9      <header className="App-header">
10        <img src={logo} className="App-logo" alt="logo" />
11        <p>
12          Edit <code>src/App.js</code> and save to reload.
13        </p>
14        <a
15          className="App-link"
16          href="https://reactjs.org"
17          target="_blank"
18          rel="noopener noreferrer"
19        >
20          Learn React
21        </a>
22      </header>
23    </div>
24  );
25}
26
27export default App;

然后更换返回声明中的所有内容以返回一组<div>标签,这样你就可以获得一个有效的页面,不会返回任何内容。

 1[label react-hooks-timer/src/App.js]
 2import React from 'react';
 3import logo from './logo.svg';
 4import './App.css';
 5
 6function App() {
 7  return (
 8    <div>
 9    </div>
10  )
11}
12
13export default App;

然后,删除./logo.svg导入标志的行。

保存和退出文本编辑器。

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

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

1rm src/logo.svg

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

步骤二:计算剩余时间

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

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

1[label react-hooks-timer/src/App.js]
2// ...
3
4const calculateTimeLeft = () => {
5
6};
7
8// ...

接下来,在函数中,你会使用JavaScript的日期对象来找到当前的年份

创建一个名为的变量,将其设置为JavaScript的日期方法Date.getFullYear()

calculateTimeLeft函数中添加以下代码:

1[label react-hooks-timer/src/App.js]
2// ...
3
4const calculateTimeLeft = () => {
5  let year = new Date().getFullYear();
6}
7
8// ...

<$>[注] **注:**您可以使用JavaScript Date对象来处理日期和时间。

Date.getFullYear()方法将捕捉当前的一年。

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

calculateTimeLeft 函数中,添加一个名为 difference 的新变量,用以下代码将其设置为一个新的 Date 对象:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4const calculateTimeLeft = () => {
 5  let year = new Date().getFullYear();
 6
 7  const difference = +new Date(`10/01/${year}`) - +new Date();
 8}
 9
10// ...

日期对象前的+是指JavaScript将对象投放为整数,这为您提供了对象的Unix时刻印,以微秒为代表。

<$>[注] **注:**对于本教程,请确保您正在计算的日期设置为未来,否则您将遇到错误

要保持代码可重复使用,请使用 JavaScript 模板字母并添加变量以及 Hacktoberfest 的月份和日期。

现在,你已经计算了数毫秒的总数,直到倒计时器到期,你需要将数毫秒转换为更友好的和人读的东西。

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

在此步骤中,您将创建一个名为timeLeft的空对象,使用if语句来检查剩余时间,并使用数学和模块(%)运算符计算小时,分钟和秒的总数。

首先,创建一个名为timeLeft的空白对象,然后在如果语句中填写天、小时、分钟和秒。

calculateTimeLeft函数中添加以下代码:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4const calculateTimeLeft = () => {
 5  let year = new Date().getFullYear();
 6  let difference = +new Date(`10/01/${year}`) - +new Date();
 7
 8  let timeLeft = {};
 9}
10
11// ...

现在创建一个如果语句,将比较差异变量,看看它是否大于0

将此代码添加到calculateTimeLeft函数中:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4const calculateTimeLeft = () => {
 5  let year = new Date().getFullYear();
 6  let difference = +new Date(`10/01/${year}`) - +new Date();
 7
 8  let timeLeft = {};
 9
10  if (difference > 0) {
11    timeLeft = {
12      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
13      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
14      minutes: Math.floor((difference / 1000 / 60) % 60),
15      seconds: Math.floor((difference / 1000) % 60)
16    };
17  }
18}
19
20// ...

在此代码中,你将日期、小时、分钟和秒的数字旋转下来,然后放下剩余数以获得整数值,然后比较差异,看看它是否大于0

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

将此代码添加到calculateTimeLeft函数中:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4const calculateTimeLeft = () => {
 5  let year = new Date().getFullYear();
 6  let difference = +new Date(`10/01/${year}`) - +new Date();
 7
 8  let timeLeft = {};
 9
10  if (difference > 0) {
11    timeLeft = {
12      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
13      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
14      minutes: Math.floor((difference / 1000 / 60) % 60),
15      seconds: Math.floor((difference / 1000) % 60)
16    };
17  }
18
19  return timeLeft;
20}
21
22// ...

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

步骤 4 — 更新您的应用程序状态,使用useStateuseEffect

使用 React Hooks,您可以将状态管理功能添加到现有功能组件中,而不将其转换为类。

在此步骤中,您将从 React 导入useStateuseEffect的锁定,以管理该组件的状态。

App.js文件的顶部,在导入陈述中添加useStateuseEffect:

1[label react-hooks-timer/src/App.js]
2import React, { useEffect, useState } from "react";
3
4// ...

此代码告诉 React 您想要使用这些特定的夹克及其在 React 中可用的功能。

要使倒计时器工作,您需要将我们先前编码的剩余时间方法线上来更新状态:

calculateTimeLeft函数后添加以下代码:

1[label react-hooks-timer/src/App.js]
2// ...
3
4const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
5
6// ...

这个JavaScript语法被称为 _array destructuring。

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

「timeLeft」將帶來我們的時間偏差對象,並為我們提供設定狀態的方法. 在組件負載上,「timeLeft」值被設定為目前時間偏差值。

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

<$>[注] 注: _ side effect_ 是指任何影响正在执行函数范围外的东西。

在此解决方案中,您将在useEffect链接中使用一个setTimeout方法。

React中的setTimeout方法等大多数非同步行为都是用useEffectuseState链接的组合来定义的。

<$>[注] **注:**您可以阅读更多关于何时以及如何使用诸如setTimeoutsetInterval等方法的信息,请参阅React Docs(https://reactjs.org/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often)。

useState()函数后添加以下代码:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
 5
 6useEffect(() => {
 7  const timer = setTimeout(() => {
 8    setTimeLeft(calculateTimeLeft());
 9  }, 1000);
10});
11
12// ...

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

每当timeLeft变量在状态中被更新时,useEffect会启动,每次启动时,我们会设置一个计时器为1秒(或1000ms),该计时器会更新该时间过后剩余的时间。

循环将在之后每秒继续。

为了帮助消除堆积时间和造成错误的潜力,在useEffect链接中添加clearTimeout方法。

添加一个clearTimeout方法,并将变量计时器作为参数输入:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4useEffect(() => {
 5  const timer = setTimeout(() => {
 6    setTimeLeft(calculateTimeLeft());
 7  }, 1000);
 8
 9  return () => clearTimeout(timer);
10});
11
12// ...

返回函数每次运行useEffect执行计时器,除第一次运行组件外,如果组件没有安装,则会清除时间。

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

步骤 5 — 使用Object.keys

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

首先,在useEffect链接下创建一个名为timerComponents的新变量:

1[label react-hooks-timer/src/App.js]
2// ...
3
4const timerComponents = [];
5
6// ...

timeLeft中重复键后,您将使用此变量来将剩余时间推向一个新的 JSX 组件

接下来,使用 Object.keys来重复您从您的 calculateTimeLeft 函数返回的 timeLeft 对象。

在「timerComponents」变量中添加此代码:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4const timerComponents = [];
 5
 6Object.keys(timeLeft).forEach((interval) => {
 7  if (!timeLeft[interval]) {
 8    return;
 9  }
10
11  timerComponents.push(
12    <span>
13      {timeLeft[interval]} {interval}{" "}
14    </span>
15  );
16});
17
18// ...

在这里,代码通过timeLeft对象的属性循环. 如果计时间隔具有大于零的值,它会将一个元素添加到timerComponents数组中。

<$>[注] **注:**代码中的附加 {" "} 被用来使显示剩余时间的间隔在屏幕上显示时不会相互碰撞。

{} 允许您在 JSX 中使用 JavaScript,而 "" 则添加空间 <$>

现在您已经准备好在应用程序组件返回声明中添加新的 JSX,以显示剩余时间直到 Hacktoberfest。

步骤 6 – 显示剩余时间

在此步骤中,您将添加 JSX 组件到应用程序组件的回报声明中。

要使用timerComponents数组,您需要检查其长度,然后返回它,或者让用户知道该计时器已经过期。

返回声明中添加此代码:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4return (
 5  <div>
 6    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
 7  </div>
 8);
 9
10// ...

在 React JSX 组件中,您使用三级运算符代替 JavaScript 语句如果

「timerComponents.length」代码行检查是否有任何东西在「timerComponents」阵列中,如果有,则返回,否则返回「时间已经到来!」。

接下来,您将添加两个 JSX 组件到回报声明中,以便用户知道他们正在计算什么:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4return (
 5  <div>
 6    <h1>Hacktoberfest 2020 Countdown</h1>
 7    <h2>With React Hooks!</h2>
 8    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
 9  </div>
10);
11
12// ...

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

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

1[label react-hooks-timer/src/App.js]
2// ...
3
4const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
5const [year] = useState(new Date().getFullYear());
6
7// ...

此方法将捕捉您在calculateTimeLeft函数中使用的当前年份。

然后,您可以从您的h1中删除硬代码2020并用更换:

 1[label react-hooks-timer/src/App.js]
 2// ...
 3
 4return (
 5  <div>
 6    <h1>Hacktoberfest {year} Countdown</h1>
 7    <h2>With React Hooks!</h2>
 8    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
 9  </div>
10);
11
12// ...

这将显示您的状态变量,现在它将始终有当前的一年。

Completed timer counting down to Hacktoberfest

点击此 GitHub 存储库查看完整的代码。

结论

在本教程中,您使用useStateuseEffect链接构建了倒数用户界面组件,以管理和更新应用程序的状态。

从这里开始,您可以继续使用 styling React components来创建更具吸引力的计数用户界面。

您还可以在 DigitalOcean 上观看完整的 如何在 React.js 中编码系列,了解更多关于使用 React 开发的信息。

Published At
Categories with 技术
Tagged with
comments powered by Disqus