在React组件中使用setTimeouts
setTimeout方法在一定时间后执行一个函数。这对于创建基于时间的效果非常有用,例如在加载新数据之前显示加载旋转图标几秒钟,或者在几秒钟后隐藏成功消息。然而,在React中使用传统的setTimeout可能会具有挑战性。为了保持React应用的效率,我们需要使用useEffect钩子来跟踪和清除这些超时。
让我们了解如何在React组件中处理setTimeouts:
在React组件中使用setTimeouts:
我们可以像在JavaScript中处理一样,在React组件中使用setTimeout方法。在React组件中,setTimeout方法遵循与JavaScript相同的原则。然而,我们应该注意一些注意事项。
要设置超时,我们需要在我们的React组件中使用useEffect钩子。直接在组件内部设置超时可能是一种不恰当的方法,因为每次组件重新渲染时,React都会重新生成setTimeout方法,导致新的超时。我们的应用程序将因为这些超时而迅速变得臃肿并且不可靠。由于多个状态更改,需要进行其他重新渲染。因此,我们将使用useEffect钩子为React组件创建timeout。当组件重新渲染时,useEffect钩子执行副作用。它接受一组依赖项数组以及用于处理副作用的回调函数。这些依赖项是状态变量,当它们变化时,引起这些副作用。我们将把timeout包含在useEffect钩子中以进行管理。
让我们了解在React中实现setTimeout方法的各种方法。
创建React应用:
步骤1: 创建一个项目目录,打开终端,使用以下命令创建一个名为 spinner-gfg 的React应用:
步骤2: 在创建 spinner-gfg 应用程序之后,通过输入以下命令切换到新文件夹 spinner-gfg:
项目结构: 现在,我们将修改文件夹并保留此示例所需的文件。现在,请确保您的文件结构如下:
示例1: 我们将使用setTimeout方法,在渲染一些数据之前展示一个加载动画5秒钟。
方法:创建加载动画应用程序:
- 我们将使用useEffect钩子和一个空的依赖数组,在组件挂载后创建一个定时器。
- data 状态变量存储内容, setData 函数更新内容的值。
- 当定时器结束后,数据将会显示, isLoading 状态将被设为false。
index.html: 将以下代码写入你的index.html文件,该文件位于项目目录的public文件夹中:
App.js:
App.css: 将以下代码添加到 App.css 中以为旋转加载应用程序添加样式。
index.js: 在 index.js 文件中添加以下代码。
运行应用程序的步骤: 使用下面的命令运行应用程序:
输出: 默认情况下,React项目将在端口3000上运行。您可以在浏览器中通过localhost:3000访问它。
解释: useEffect钩子函数调用一个空数组依赖,这意味着它只会在组件挂载时运行一次,并确保定时器只设置一次。isLoading状态变量控制组件的渲染。如果isLoading为true,组件将渲染一个加载旋转器。如果isLoading为false,组件将显示数据。我们可以使用setTimeout方法在useEffect钩子函数中加载数据时显示加载旋转器。
让我们了解如何在重新渲染时创建超时。
清除setTimeout:
在useEffect钩子函数中,我们可以在组件的状态改变时创建超时。然而,每次状态改变时都会生成新的超时,这可能会导致性能问题。必须清除不再需要的超时以防止潜在的内存泄漏。setTimeout方法创建一个定时器,并排队一个回调函数,在指定的时间过去后执行。如果定时器到期并且执行回调函数,超时完成。然而,如果使用相同的变量设置新的超时,上一个超时将被取消,新的超时将被启动。如果超时不在不再需要时被取消,即使设置超时的组件已经卸载,回调函数仍然可能被执行。这可能会导致资源浪费和潜在的错误,特别是如果回调函数具有不再相关的副作用。
为了避免这种情况,我们可以在创建新的超时之前清除上一个超时,使用clearTimeout方法。这对于预防我们的应用中的内存泄漏很重要,因为在组件卸载时,如果不清除setTimeout的回调函数仍然可能执行。
clearTimeout方法:
- clearTimeout取消setTimeout方法生成的超时。
- setTimeout方法返回一个timeoutId,该timeoutId传递给clearTimeout。
- timeoutId标识setTimeout函数生成的特定定时器。
语法:
这是一个示例,展示了在重新渲染时如何在React中清除setTimeouts并创建定时器:
示例2: 显示在指定时间后消失的警告消息。
步骤:创建警告消息组件: 我们将显示一个警告消息5秒钟,然后使用setTimeout方法隐藏它。
- 我们将使用 useEffect 钩子在 showWarning 状态为true时设置计时器,并在组件卸载或showWarning状态改变时取消计时器。
- useEffect钩子在组件渲染时调用,意味着每次组件挂载且showWarning状态为true时都会设置一个计时器。
- 为了在组件卸载或showWarning状态改变时取消计时器,我们需要一种存储 计时器ID 并从useEffect钩子的清理函数中访问它的方法。这就是 useRef 钩子的用武之地。
- useRef钩子允许我们创建一个可变的 ref ,在重新渲染时保持不变,可以用于存储计时器ID。当组件挂载时,计时器ID存储在timerId ref的 current 属性中。
- 当组件卸载或showWarning状态改变时,useEffect钩子的清理函数被调用,并使用存储在timerId ref 中的计时器ID取消计时器。
App.js:
App.css: 在 App.css 中添加以下代码以给消息应用程序添加样式。
运行应用程序的步骤:
使用以下命令运行应用程序:
输出:
解释:
组件挂载时,使用一个空的showWarning数组调用useEffect钩子,这意味着效果只会运行一次。if (showWarning)条件为false,所以计时器不会被设置。当用户点击Show Warning按钮时,会调用handleClick函数,该函数将showWarning状态设置为true。这会导致组件重新渲染并再次调用useEffect钩子。这次,if (showWarning)条件为true,所以使用setTimeout设置计时器,在5秒后隐藏警告消息。
如果用户在5秒内再次点击Show Warning按钮,则showWarning状态将再次被设置为true,导致组件重新渲染并再次调用useEffect钩子。这将取消上一个计时器,并设置一个新计时器,在5秒后隐藏警告消息。
如果用户在5秒内离开页面,则组件将被卸载,并调用useEffect钩子的清理函数。清理函数使用保存在timerId引用中的计时器ID来调用clearTimeout,取消计时器并防止回调函数被执行。
这样我们就可以在5秒后自动隐藏警告消息,而不会产生不必要的副作用。