ReactJS 自定义 useInterval Hook
JavaScript 的 setInterval() 方法可以重复以固定时间延迟执行一个函数。在 React 中使用 setInterval 方法可能会有一些挑战。例如,如果我们想要更新延迟参数,可能需要处理很多生命周期方法。为了避免这个麻烦,我们可以使用一个自定义的 useInterval hook。
useInterval hook 以声明式的方式实现了 setInterval 方法。通过结合 setInterval 和 clearInterval 方法,useInterval hook 在挂载后设置一个间隔,并在卸载时清除它。我们可以简单地声明一个带有延迟的间隔。useInterval hook 的参数可以是动态的,这使得我们可以动态调整延迟而不必担心间隔的开始或结束。
在使用上,useInterval 与 setInterval 很相似:
语法:
useInterval(() => {
// func
}, delay);
React的useInterval Hook接受一个函数和一个延迟作为参数,其中,
- func: 这是一个延迟后重复执行的函数。
- delay: 这是函数连续执行之间的时间间隔。
注意: 这些参数是动态的,不像setInterval方法中的参数。
让我们看一个在React中如何使用useInterval自定义hook的示例:
步骤: 我们将使用useInterval自定义hook创建一个具有动态可调节延迟的计数器。
实现和设置创建React应用程序:
步骤1: 创建一个项目目录,然后进入终端,使用以下命令创建一个名为counter的React应用:
npx create-react-app counter
创建计数器应用程序后,通过输入以下命令切换到新的counter文件夹:
cd counter
步骤2: 修改您的项目结构。在src文件夹中添加一个 useInterval.js 文件。我们将修改文件夹并保留此示例所需的文件。现在,请确保您的文件结构如下所示:
步骤3: 将以下代码包含在位于项目目录的public文件夹中的 index.html 文件中。
文件名:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description"
content="Web site created using create-react-app" />
<title>Counter App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
步骤4: 创建用于计数器应用的useInterval自定义hook。在useInterval.js文件中,我们将编写一个函数来创建一个自定义的useInterval hook,可以在我们的计数器应用中使用。
- useInterval函数接受回调函数和延迟作为参数。
- 这个延迟不是一个硬编码的数字,而是一个动态参数。
- 我们将使用 useRef() hook 为回调函数创建一个 ref。
- useEffect hook 清理之前的效果,但 setInterval 方法仍然引用旧状态,因为我们没有重置时间。
- 因此,我们创建一个savedCallback作为可变的变量,它在渲染之间保持不变,并跟踪以前的回调函数。
- 我们将回调函数保存为savedCallback.current。
- 我们可以在设置间隔时访问这个值。
- 由于延迟在渲染之间发生改变,我们将它作为useEffect的依赖项传入。
- 因此,每当延迟时间被调整时,计数器会重置。
文件名:useInterval.js
import React, { useState, useEffect, useRef } from 'react';
// creating the custom useInterval hook
export function useInterval(callback, delay) {
// Creating a ref
const savedCallback = useRef();
// To remember the latest callback .
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// combining the setInterval and
//clearInterval methods based on delay.
useEffect(() => {
function func() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(func, delay);
return () => clearInterval(id);
}
}, [delay]);
}
步骤5: 创建计数器组件。
- 我们将使用 useState 和 useInterval 自定义 hooks 来实现计数器。
- 我们将在自定义的 useInterval hook 中传入逻辑和延迟参数。
- 我们将有一个按钮来切换播放或暂停计数器。
- 我们将在输入框中输入延迟时间并点击播放按钮。
- 延迟将有一个空值来暂停计数器。
文件名: App.js
import './App.css';
import { useState } from 'react'
//Import the custom hook
import { useInterval } from './useInterval'
export default function App() {
// The counter
const [count, setCount] = useState(0)
// Updating the delay dynamically
const [delay, setDelay] = useState()
// Toggle play pause the counter
const [isPlaying, setPlaying] = useState(false)
useInterval(
() => {
//counter function
setCount(count + 1)
},
// Passing in the delay parameter. null stops the counter.
isPlaying ? delay : null,
)
const handleChange = (e) => {
setDelay(e.target.value)
}
return (
<>
<div className='counterStyle'>
<h1>Let's begin counting!</h1>
<h1>{count}</h1>
<button className='btn' onClick={() =>
setPlaying(!isPlaying)}>
{isPlaying ?
'Pause⏸' :
'Play ▶'}
</button>
<p>
<label htmlFor="delay">Delay: </label>
<input
type="text"
name="delay"
onChange={handleChange}
value={delay}
placeholder='Enter delay time'
/>
</p>
</div>
</>
)
}
步骤6: 将以下代码添加到 App.css 以样式化计数器应用程序。
文件名:App.css
.counterStyle {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 2px solid darkGreen;
margin: 2rem;
}
.btn {
background-color: darkgreen;
color: white;
border-radius: 10px;
font-size: 1rem;
padding: 10px;
}
步骤7: 将以下代码添加到 index.js 文件中。index.js文件用作主要入口点,其内部将在DOM的根ID处呈现App.js文件。
文件名:index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
运行应用程序的步骤: 使用以下命令运行我们的应用程序:
npm start
输出: 默认情况下,React项目将在3000端口运行。您可以在浏览器上通过localhost:3000访问它。您可以通过输入延迟时间(以毫秒为单位)并点击播放按钮来启动计数器。