如何在React.js中执行debounce ?
我想撤消handleOnChange。
我尝试debounce(这。handleOnChange, 200)但它不起作用。
function debounce(fn, delay) {
var timer = null;
return function() {
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
var SearchBox = React.createClass({
render: function() {
return <input type="search" name="p" onChange={this.handleOnChange} />;
},
handleOnChange: function(event) {
// make ajax call
}
});
有一个使用react钩子的简单方法。
步骤1:定义一个状态来维护搜索的文本
const [searchTerm, setSearchTerm] = useState('')
步骤2:使用useEffect捕获搜索Term中的任何变化
useEffect(() => {
const delayDebounceFn = setTimeout(() => {
if (searchTerm) {
// write your logic here
}
}, 400)
return () => clearTimeout(delayDebounceFn)
}, [searchTerm])
步骤3:编写一个函数来处理输入更改
function handleInputChange(value) {
if (value) {
setSearchTerm(value)
}
}
就这些!在需要时调用此方法
你可以在ReactJS钩子中使用一个use-debounce包。
从包的README:
import { useDebounce } from 'use-debounce';
export default function Input() {
const [text, setText] = useState('Hello');
const [value] = useDebounce(text, 1000);
return (
<div>
<input
defaultValue={'Hello'}
onChange={(e) => {
setText(e.target.value);
}}
/>
<p>Actual value: {text}</p>
<p>Debounce value: {value}</p>
</div>
);
}
从上面的示例中可以看到,它设置为每秒钟更新一次变量值(1000毫秒)。
2022 -使用useEffect钩子
此时最好的选择是使用useEffect钩子。useEffect允许您设置一个函数,该函数可以修改状态以响应某些异步事件。debounging是异步的,因此useEffect可以很好地用于此目的。
如果从钩子返回一个函数,返回的函数将在钩子再次被调用之前被调用。这让您可以取消之前的超时,有效地解除函数。
例子
这里我们有两个状态,value和tempValue。设置tempValue将触发useEffect钩子,该钩子将启动一个1000ms超时,该超时将调用一个函数将tempValue复制为value。
钩子返回一个取消定时器设置的函数。当钩子再次被调用时(即按下另一个键),超时被取消并重置。
const DebounceDemo = () => {
const [value, setValue] = useState();
const [tempValue, setTempValue] = useState();
// This hook will set a 1000 ms timer to copy tempValue into value
// If the hook is called again, the timer will be cancelled
// This creates a debounce
useEffect(
() => {
// Wait 1000ms before copying the value of tempValue into value;
const timeout = setTimeout(() => {
setValue(tempValue);
}, 1000);
// If the hook is called again, cancel the previous timeout
// This creates a debounce instead of a delay
return () => clearTimeout(timeout);
},
// Run the hook every time the user makes a keystroke
[tempValue]
)
// Here we create an input to set tempValue.
// value will be updated 1000 ms after the hook is last called,
// i.e after the last user keystroke.
return (
<>
<input
onChange={
({ target }) => setTempValue(target.value)
}
/>
<p>{ value }</p>
</>
)
}
您可以使用引用变量来存储计时器,然后将其清除。下面是一个不使用任何第三方包在react中实现deboundation的例子
import { useState, useRef } from "react";
import "./styles.css";
export default function App() {
// Variables for debouncing
const [text, setText] = useState("");
const timer = useRef();
// Variables for throtteling
const [throttle, setThrottle] = useState(false)
const handleDebouncing = ({ target }) => {
clearTimeout(timer.current)
timer.current = setTimeout(() => {
callApi();
}, 300);
setText(target.value);
};
const handleThrottleing = () => {
callApi()
setThrottle(true)
setTimeout(() => {
setThrottle(false)
}, 2000)
}
const callApi = () => {
console.log("Calling Api");
};
return (
<div className="App">
<input type="text" onChange={handleDebouncing} />
<button onClick={handleThrottleing} disabled={throttle} >Click me to see throtteling</button>
</div>
);
}
有点晚了,但应该有帮助。
创建这个类(它是用typescript写的,但是很容易转换成javascript)
export class debouncedMethod<T>{
constructor(method:T, debounceTime:number){
this._method = method;
this._debounceTime = debounceTime;
}
private _method:T;
private _timeout:number;
private _debounceTime:number;
public invoke:T = ((...args:any[])=>{
this._timeout && window.clearTimeout(this._timeout);
this._timeout = window.setTimeout(()=>{
(this._method as any)(...args);
},this._debounceTime);
}) as any;
}
要使用
var foo = new debouncedMethod((name,age)=>{
console.log(name,age);
},500);
foo.invoke("john",31);