我有这堂课:
export default class Search extends Component {
throttle(fn, threshhold, scope) {
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
}
}
render() {
return (
<div>
<input type='text' ref='input' onChange={this.throttle(this.handleSearch,3000,this)} />
</div>
)
}
handleSearch(e) {
let text = this.refs.input.value;
this.someFunc();
//this.props.onSearch(text)
}
someFunc() {
console.log('hi')
}
}
所有这些代码都会每隔3秒注销hi
- throttle
调用handleSearch
方法来处理此问题
一旦我取消注释这一行:
this.props.onSearch(text)
限制方法停止生效,控制台只有在没有暂停的情况下按下键时才会注销hi
,并且还会调用oSearch
函数。
此onSearch
方法是从主应用程序传递的prop方法:
<Search onSearch={ text => dispatch(search(text)) } />
redux dispatch会触发redux搜索操作,如下所示:
export function searchPerformed(search) {
return {
type: SEARCH_PERFORMED
}
}
我不知道为什么会发生这种情况 - 我猜测它与redux有关,因为当handleSearch调用onSearch时会出现问题,而onSearch会在父组件中触发redux dispatch。
答案 0 :(得分:1)
问题是它第一次执行时会转到else,它会调用dispatch函数。减速器可能会立即更新某些状态,并导致重新渲染;重新渲染会导致输入再次创建,并带有一个新的节流闭合&#39;这又是空的&#39; last&#39;和&#39; deferTimer&#39; - &GT;每次都去其他地方,因此立即更新。
答案 1 :(得分:1)
正如迈克指出的那样,如果组件不需要更新,那么只是不更新组件就可以获得正确的行为。
在我的情况下,我有一个组件需要每隔几秒轮询一次服务器以获取更新,直到一些状态派生的prop改变了值(例如&#39; pending&#39; vs&#39; complete&#39; ;)
每次新数据进入时,组件都会重新渲染,并再次调用动作创建者,并限制动作创建者无法正常工作。
我只需将相关的动作创建者交给组件挂载的setInterval即可解决。是的,它是渲染上发生的副作用,但它很容易推理,实际的状态变化仍然通过调度员。
如果您想保持纯净,或者您的使用案例更复杂,请查看https://github.com/pirosikick/redux-throttle-actions。
答案 2 :(得分:0)
感谢luanped帮我解决了这个问题。有了这个,我就能找到一个简单的解决方案。搜索组件不需要更新,因为输入是不受控制的组件。为了解决我遇到的周期性问题,我已经使用了shouldComponentUpdate来阻止它重新渲染:
NULL
我还把油门移到了构造函数中,因此只能有一次油门实例。
我认为这是一个很好的解决方案,但我只是刚刚开始学习反应,所以如果有人能指出这种方法的问题,那将是受欢迎的。