翻译文章----How to use setInterval() method inside React components

253 阅读4分钟

原文链接:How to use setInterval() method inside React components

最近在写自己的小项目时,在React中实现定时器的功能时遇到了一些问题,在网上查了各种资料之后看到了这篇文章,觉得写的不错,也帮我解决了这个问题,索性就翻译成中文,给遇到过这个问题的和即将遇到这个问题的小伙伴提供一种解决办法。

正文开始:

如何在React组件中使用setInterval()方法

学习如何在React组件中正确的使用setInterval()和clearInterval()方法。发表于2021年6月14日


有时,你可能想在React组件中使用setInterval()方法,因此这个React组件也许会运行一个特定间隔的代码

这个教程将会向你展示如何在当你的组件被挂载(渲染)或者是当一个按钮被用户点击就运行setInterval()方法

这个教程使用React的函数组件当作代码用例,对于类组件,请移步这个教程:如何在React类组件中使用SetInterval()方法

让我们以组件被挂载后的间隔开始。

在组件被挂载后就运行setInterval()

如果你想要你的组件被渲染到屏幕上就开始执行间隔,你可以把你的setInverval()方法放到一个useEffect钩子中。

代码跟下面的代码类似

 useEffect(() => {
   setInterval(() => {
     /*
         Run a function or set any state here
     */
   }, 1000);
 }, []);

通过结合setInterval()方法和useEffect()钩子和useState钩子你可以创造一个计时器,计算自从组件被挂载后过去了多少秒。

在下面这个应用组件中:

 import React, { useState, useEffect } from "react";
 ​
 const App = () => {
   const [count, setCount] = useState(0);
 ​
   useEffect(() => {
     setInterval(() => {
       setCount(prevCount => prevCount + 1);
     }, 1000);
   }, []);
 ​
   return <h1>The component has been rendered for {count} seconds</h1>;
 };
 ​
 export default App;

因为上面这个useEffect()钩子有一个空的依赖数组,它将在这个组件的生命周期内只被执行一次,意思就是setIntercal()方法每隔1000毫秒就会执行一次setCount().

请注意,你需要将之前的数据变量传递给setCount()方法去不断的增加count的值。

如果你使用下面这种方式来增加count的值:

 setCount(count + 1);

这个count将会被困于0 + 1 = 1因为当setInterval()调用时,变量count的值是0。

如果你想要清除setInterval()方法,避免内存泄漏,你需要做两件事情:

  • 保存通过setInverval()方法返回的循环ID
  • 更改useEffect()钩子,让它返回一个函数,在返回的函数中调用clearInterval()方法,并且将之前setInterval()方法返回的ID传递给它(clearInterval)

这是一个更改过了的useEffect(),并且实现了上面两步

 useEffect(() => {
   const intervalId = setInterval(() => {
     setCount(prevCount => prevCount + 1);
   }, 1000);
 ​
   return () => clearInterval(intervalId);
 }, []);

这就是如何在组件挂载后执行setInterval()的方法。现在让我们一起看如何在用户点击了一个按钮之后运行setInterval()

从一个React按钮点击事件中运行setInterval()

为了在用户点击一个按钮之后执行setInterval()方法,你需要将setInterval()方法放入到你的按钮点击事件处理属性中。

这里有一个例子:

 const App = () => {
   const [count, setCount] = useState(0);
 ​
   const handleClick = () => {
     setInterval(() => {
       setCount(prevCount => prevCount + 1);
     }, 1000);
   }
 ​
   return(
     <div>
       <h1>The component has been rendered for {count} seconds</h1>
       <button onClick={handleClick}>Start counting</button>
     </div>
   );
 };
 ​
 export default App;

为了停止按钮点击循环,你需要将setInterval()方法返回的的循环ID保存为一个状态值。

比如,向下面一样创建另一个叫做interval的状态。

 const [intervalId, setIntervalId] = useState(0);
 ​
 const handleClick = () => {
   const newIntervalId = setInterval(() => {
     setCount(prevCount => prevCount + 1);
   }, 1000);
   setIntervalId(newIntervalId);
 }

下面,改变handleClick()函数并且添加一个if模块,这个模块首先检查intervalId

如果这个interval()变量是真值,然后:

  • 调用clearInterval()函数,并且以参数的形式传递intervalId
  • 调用setIntervalId()并且将值设回0
  • 编写return语句,让handleClick()停止执行

下面的代码实现了上面三点:

 const handleClick = () => {
   if(intervalId) {
     clearInterval(intervalId);
     setIntervalId(0);
     return;
   }
 ​
   const newIntervalId = setInterval(() => {
     setCount(prevCount => prevCount + 1);
   }, 1000);
   setIntervalId(newIntervalId);
 }

最终,根据interval的值更改按钮标签来开始计数或者是停止计数,

这里是完整的代码

 const App = () => {
   const [count, setCount] = useState(0);
   const [intervalId, setIntervalId] = useState(0);
 ​
   const handleClick = () => {
     if (intervalId) {
       clearInterval(intervalId);
       setIntervalId(0);
       return;
     }
 ​
     const newIntervalId = setInterval(() => {
       setCount(prevCount => prevCount + 1);
     }, 1000);
     setIntervalId(newIntervalId);
   };
 ​
   return (
     <div>
       <h1>The component has been rendered for {count} seconds</h1>
       <button onClick={handleClick}>
         {intervalId ? "Stop counting" : "Start counting"}
       </button>
     </div>
   );
 };
 ​
 export default App;

这就是你如何在一个React组件中去使用setInterval()的方法。