使用 React 钩子去抖动
如何使用 React hooks 去抖动 onChange 事件。 tl;博士 useEffect(() => { const timeout = setTimeout(() => someFunction(), 400); return () => { clearTimeout(timeout); }; }, [dependency]); 在效果中使用 setTimeout 并在下一次效果调用之
如何使用 React hooks 去抖动 onChange 事件。
tl;博士
useEffect(() => {
const timeout = setTimeout(() => someFunction(), 400);
return () => { clearTimeout(timeout); };
}, [dependency]);
在效果中使用 setTimeout 并在下一次效果调用之前将其清除。这只会在依赖数组 400 毫秒未更改时调用 someFunction()。这种模式非常适合发出网络请求或调用其他昂贵的函数。
重构滞后的输入
用户名组件有两种状态:用户名和有效。在每次输入更改时,我们将用户名设置为新值,并计算并设置有效性。
这可行,但这是一个糟糕的用户体验,因为输入感觉非常滞后。验证需要很长时间,并且键盘事件感觉不是即时的。
在这里,我正在用一个大的 for 循环来烧循环,但你可以想象在它的位置发出一个网络请求。
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
const validate = value => {
// expensive validation
for (var x = 1; x < 500000000; x++) {
value.length < x;
}
if (value.length > 5) {
return "max length is 5";
}
if (value.length === 0) {
return "please select your username";
}
return "looks good";
};
const Username = () => {
const [username, setUsername] = useState("");
const [valid, setValid] = useState(undefined);
return (
<div>
<div>Username</div>
<input
type="text"
value={username}
onChange={e => {
const value = e.target.value;
setUsername(value);
setValid(validate(value));
}}
/>
<div>{valid}</div>
</div>
);
};
ReactDOM.render(<Username />, document.getElementById("main"));
重构消除滞后
我们仍然想检查用户名是否有效,但我们想让它为用户提供良好的体验。目标是仅在输入暂停后验证用户输入。我们不关心在用户输入时验证输入,我们只想在他们暂停片刻时验证它。
从 onChange 事件中移除 setValid 调用。
我们只想在用户停止输入一段时间后调用 setValid。现在,onChange 只更新用户名。输入将不再感觉滞后,但不会触发验证。
** useEffect 钩子**
我们将使用“useEffect”钩子来计算和设置验证。 useEffect 钩子有两个参数,效果函数和依赖数组。当依赖数组中的值发生变化时,效果会触发。在我们的例子中,我们想在用户名改变时触发回调,所以我们把它放在依赖数组中。
仍然滞后
useEffect(() => {
setValid(validate(username));
}, [username]);
只要用户名更改,效果就会触发。我们无法检查和设置效果中的有效性,因为我们将面临与以前相同的问题:输入滞后。因此,我们需要一种方法,仅在用户名在一定时间内未更改后才调用验证函数。
使用 setTimeout
setTimeout 有两个参数:回调和毫秒数。在此示例中,我们要检查并设置回调中的有效性。我选择了 400 毫秒作为超时。现在,每次用户名更改时都会设置超时并触发验证。
还是不好:
useEffect(() => {
const timer = setTimeout(() => {
setValid(validate(username));
}, 400);
}, [username]);
不过,这并不理想。每次按键都会产生超时,并且每次按键都会调用验证,只是延迟了一点。
使用效果清理
useEffect 提供了一种清理效果的方法。如果你从一个效果返回一个函数,那么它将在下一个效果之前触发。这正是我们所需要的。我们可以在创建新超时之前返回一个清除旧超时的函数。
useEffect(() => {
setValid("");
const timer = setTimeout(() => {
setValid(validate(username));
}, 400);
return () => {
clearTimeout(timer);
};
}, [username]);
这是您仅在用户名 400 毫秒未更改后调用验证函数的方式。
完整代码
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
const validate = value => {
// expensive validation
for (var x = 1; x < 500000000; x++) {
value.length < x;
}
if (value.length > 5) {
return "max length is 5";
}
if (value.length === 0) {
return "please select your username";
}
return "looks good";
};
const Username = () => {
const [username, setUsername] = useState("");
const [valid, setValid] = useState(undefined);
useEffect(() => {
// clear the valid message so nothing is displayed while typing
setValid("");
// create the timer
const timer = setTimeout(() => {
setValid(validate(username));
}, 400);
// return a cleanup function that clears the timeout
return () => {
clearTimeout(timer);
};
}, [username]);
return (
<div>
<div>Username</div>
<input
type="text"
value={username}
onChange={e => {
const value = e.target.value;
setUsername(value);
}}
/>
<div>{valid}</div>
</div>
);
};
延伸阅读
查看 useEffect 的反应文档:https://reactjs.org/docs/hooks-effect.html
更多推荐
所有评论(0)