如何在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
}
});
如果你只需要在一个按钮中执行一个请求数据的debounce,提供的代码可能对你有帮助:
创建一个函数,以防止在请求为真或假时使用默认的条件语句
实现useState钩子和useEffect钩子
const PageOne = () => {
const [requesting, setRequesting] = useState(false);
useEffect(() => {
return () => {
setRequesting(false);
};
}, [requesting]);
const onDebounce = (e) => {
if (requesting === true) {
e.preventDefault();
}
// ACTIONS
setLoading(true);
};
return (
<div>
<button onClick={onDebounce}>Requesting data</button>
</div>
)
}
避免使用event.persist()——你想让React回收合成事件。我认为无论你使用类还是钩子,最干净的方法是将回调函数分成两部分:
没有deboundation的回调
只使用您需要的事件片段调用已撤销的函数(这样合成的事件就可以循环使用)
类
handleMouseOver = throttle(target => {
console.log(target);
}, 1000);
onMouseOver = e => {
this.handleMouseOver(e.target);
};
<div onMouseOver={this.onMouseOver} />
功能
const handleMouseOver = useRef(throttle(target => {
console.log(target);
}, 1000));
function onMouseOver(e) {
handleMouseOver.current(e.target);
}
<div onMouseOver={this.onMouseOver} />
注意,如果你的handleMouseOver函数从组件中使用状态,你应该使用usemo而不是useRef,并将它们作为依赖项传递,否则你将使用过时的数据(当然不适用于类)。
这个解决方案不需要任何额外的库,它也会在用户按下enter时启动:
const debounce = (fn, delay) => {
let timer = null;
return function() {
const context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(context, args);
}, delay);
};
}
const [search, setSearch] = useState('');
const [searchFor, setSearchFor] = useState(search);
useEffect(() => {
console.log("Search:", searchFor);
}, [searchFor]);
const fireChange = event => {
const { keyCode } = event;
if (keyCode === 13) {
event.preventDefault();
setSearchFor(search);
}
}
const changeSearch = event => {
const { value } = event.target;
setSearch(value);
debounceSetSearchFor(value);
};
const debounceSetSearchFor = useCallback(debounce(function(value) {
setSearchFor(value);
}, 250), []);
输入可以是这样的:
<input value={search} onKeyDown={fireChange} onChange={changeSearch} />
你必须使用useCallback,正如在这篇博客中提到的:
https://www.freecodecamp.org/news/debounce-and-throttle-in-react-with-hooks/
import React, { useCallback } from 'react';
import debounce from 'debounce'; // or another package
function App() {
...
const debouncedSave = useCallback(
debounce(x => foo(x), 1000),
[], // will be created only once initially
);
...
}
你也可以使用自己编写的mixin,就像这样:
var DebounceMixin = {
debounce: function(func, time, immediate) {
var timeout = this.debouncedTimeout;
if (!timeout) {
if (immediate) func();
this.debouncedTimeout = setTimeout(function() {
if (!immediate) func();
this.debouncedTimeout = void 0;
}.bind(this), time);
}
}
};
然后像这样在你的组件中使用它:
var MyComponent = React.createClass({
mixins: [DebounceMixin],
handleClick: function(e) {
this.debounce(function() {
this.setState({
buttonClicked: true
});
}.bind(this), 500, true);
},
render: function() {
return (
<button onClick={this.handleClick}></button>
);
}
});
你可以在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毫秒)。