你如何在 React.js 中执行去抖动?
我想去抖动handleOnChange。
我尝试使用 debounce(this.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
}
});
原文由 Chetan Ankola 发布,翻译遵循 CC BY-SA 4.0 许可协议
2019:尝试 hooks + promise 去抖动
这是我如何解决这个问题的最新版本。我会用:
这是一些初始接线,但您正在自己编写原始块,您可以制作自己的自定义挂钩,这样您只需执行一次。
然后你可以使用你的钩子:
你会发现这个例子在 这里 运行,你应该阅读 react-async-hook 文档了解更多细节。
2018:尝试 promise 去抖动
我们经常希望对 API 调用进行去抖动处理,以避免后端被无用的请求淹没。
在 2018 年,使用回调 (Lodash/Underscore) 对我来说感觉很糟糕并且容易出错。由于 API 调用以任意顺序解析,因此很容易遇到样板文件和并发问题。
我创建了一个考虑 React 的小库来解决你的痛苦: awesome-debounce-promise 。
这不应该比那更复杂:
debounced 函数确保:
this.setState({ result });
最后,如果您的组件卸载,您可能会添加另一个技巧:
请注意, Observables (RxJS) 也非常适合去抖动输入,但它是一种更强大的抽象,可能更难正确学习/使用。
< 2017:还想使用回调去抖动吗?
这里的重要部分是 为每个组件实例创建一个去抖动(或节流)函数。您不想每次都重新创建去抖动(或节流)功能,也不希望多个实例共享相同的去抖动功能。
我没有在这个答案中定义去抖动函数,因为它并不真正相关,但这个答案将与下划线或 lodash 的
_.debounce
以及任何用户提供的去抖动函数完美配合。好主意:
因为去抖函数是有状态的,我们必须为 每个组件实例创建一个去抖函数。
ES6(类属性) :推荐
ES6(类构造器)
ES5
请参阅 JsFiddle :3 个实例每个实例生成 1 个日志条目(全局生成 3 个)。
不是一个好主意:
它不会起作用,因为在类描述对象创建期间,
this
不是对象本身创建的。this.method
不会返回您期望的内容,因为this
上下文不是对象本身(顺便说一句,它实际上并不存在,因为它刚刚被创建)。不是一个好主意:
这次您有效地创建了一个调用您的
this.method
的去抖函数。问题是你在每次debouncedMethod
调用时重新创建它,所以新创建的去抖功能对以前的调用一无所知!随着时间的推移,您必须重复使用相同的去抖动函数,否则不会发生去抖动。不是一个好主意:
这在这里有点棘手。
该类的所有已安装实例将共享相同的去抖动函数,而且通常这不是您想要的!。请参阅 JsFiddle :3 个实例在全球范围内仅生成 1 个日志条目。
您必须 为每个组件实例 创建一个去抖动函数,而不是在类级别创建一个由每个组件实例共享的去抖动函数。
照顾 React 的事件池
这是相关的,因为我们经常想要去抖动或限制 DOM 事件。
在 React 中,您在回调中收到的事件对象(即
SyntheticEvent
)被合并(现在已 记录)。这意味着在调用事件回调后,您收到的 SyntheticEvent 将以空属性放回池中以减少 GC 压力。因此,如果您访问
SyntheticEvent
与原始回调异步的属性(如果您限制/去抖动可能就是这种情况),您访问的属性可能会被删除。如果您希望事件永远不会放回池中,可以使用persist()
方法。没有持久化(默认行为:合并事件)
第二个(异步)将打印
hasNativeEvent=false
因为事件属性已被清理。随着坚持
第二个(异步)将打印
hasNativeEvent=true
因为persist
允许您避免将事件放回池中。您可以在这里测试这两种行为: JsFiddle
阅读 Julen 的回答,了解使用
persist()
和节流/去抖功能的示例。