如何在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钩子工具包库react-use,那么有一个名为useDebounce()的实用工具钩子,它以一种相当优雅的方式实现了谴责逻辑。
const [query, setQuery] = useState('');
useDebounce(
() => {
emitYourOnDebouncedSearchEvent(query);
},
2000,
[query]
);
return <input onChange={({ currentTarget }) => setQuery(currentTarget.value)} />
有关详细信息,请直接检查库的github页面。
https://github.com/streamich/react-use/blob/master/docs/useDebounce.md
有点晚了,但应该有帮助。
创建这个类(它是用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);
Julen的解决方案有点难以阅读,这里有更清晰和准确的反应代码,供那些根据标题而不是问题的微小细节绊倒他的人使用。
Tl;dr版本:当你要更新到观察者发送调用一个调度方法,反过来实际上会通知观察者(或执行ajax等)
使用示例组件jsfiddle完成jsfiddle
var InputField = React.createClass({
getDefaultProps: function () {
return {
initialValue: '',
onChange: null
};
},
getInitialState: function () {
return {
value: this.props.initialValue
};
},
render: function () {
var state = this.state;
return (
<input type="text"
value={state.value}
onChange={this.onVolatileChange} />
);
},
onVolatileChange: function (event) {
this.setState({
value: event.target.value
});
this.scheduleChange();
},
scheduleChange: _.debounce(function () {
this.onChange();
}, 250),
onChange: function () {
var props = this.props;
if (props.onChange != null) {
props.onChange.call(this, this.state.value)
}
},
});
/**
* Returns a function with the same signature of input `callback` (but without an output) that if called, smartly
* executes the `callback` in a debounced way.<br>
* There is no `delay` (to execute the `callback`) in the self-delayed tries (try = calling debounced callback). It
* will defer **only** subsequent tries (that are earlier than a minimum timeout (`delay` ms) after the latest
* execution). It also **cancels stale tries** (that have been obsoleted because of creation of newer tries during the
* same timeout).<br>
* The timeout won't be expanded! So **the subsequent execution won't be deferred more than `delay`**, at all.
* @param {Function} callback
* @param {number} [delay=167] Defaults to `167` that is equal to "10 frames at 60 Hz" (`10 * (1000 / 60) ~= 167 ms`)
* @return {Function}
*/
export function smartDebounce (callback, delay = 167) {
let minNextExecTime = 0
let timeoutId
function debounced (...args) {
const now = new Date().getTime()
if (now > minNextExecTime) { // execute immediately
minNextExecTime = now + delay // there would be at least `delay` ms between ...
callback.apply(this, args) // ... two consecutive executions
return
}
// schedule the execution:
clearTimeout(timeoutId) // unset possible previous scheduling
timeoutId = setTimeout( // set new scheduling
() => {
minNextExecTime = now + delay // there would be at least `delay` ms between ...
callback.apply(this, args) // ... two consecutive executions
},
minNextExecTime - now, // 0 <= timeout <= `delay` ... (`minNextExecTime` <= `now` + `delay`)
)
}
debounced.clear = clearTimeout.bind(null, timeoutId)
return debounced
}
/**
* Like React's `useCallback`, but will {@link smartDebounce smartly debounce} future executions.
* @param {Function} callback
* @param {[]} deps
* @param {number} [delay=167] - Defaults to `167` that is equal to "10 frames at 60 Hz" (`10 * (1000 / 60) ~= 167 ms`)
*/
export const useDebounced = (callback, deps, delay = 167) =>
useMemo(() => smartDebounce(callback, delay), [...deps, delay])