使用setTimeout避免React

时间:2018-03-05 17:19:28

标签: reactjs settimeout anti-patterns

我经常使用一种模式,我认为必须是反模式,但我不知道更好的选择。

有时我的组件可能会收到一个或多个意味着需要重新渲染的事件。有时情况是我不知道将调用事件处理程序的次数。为了防止多次重新渲染由于多次调用处理程序,我做了类似这样的事情:

 _myEventHandler() { // may be called multiple times between renders
   if (!this._updateQueued) {
     this._updateQueued = true;
     this._updateTimer = setTimeout(() => {
       this._updateQueued = false;
       this.forceUpdate();
     }, 0);
   }
 }

这里的问题是我觉得由于代码停止和事件循环启动之间的延迟而无法实现性能。

一个真实世界的例子是当我使用react-visibility-sensor并且我有多个元素一次改变它们的可见性时,我不想为每个元素重新渲染,而我只想要一个收到所有更新后重新渲染。

还有另一种更好的方式来处理多个电话吗?

顺便说一句:如果您要使用上述黑客,请不要忘记在clearTimout(this._updateQueued)

中致电componentWillUnmount

2 个答案:

答案 0 :(得分:1)

去抖动将减少某段代码运行的次数,无论它被调用的频率如何。这是一个相当简单的实现。

const debounce = (callable, time) => {
  let timeout;

  return function() {
    const functionCall = () => callable.apply(this, arguments);

    clearTimeout(timeout);
    timeout = setTimeout(functionCall, time);
  };
};

这就是如何使用它。

const debouncedIteration = debouce(() => {
   console.log("Iteration"); // This will be called once every 1000 milliseconds.
}, 1000);

while (true) {
   debouncedIteration();
}

答案 1 :(得分:1)

您可以使用此生命周期方法shouldComponentUpdate避免重新渲染(@fungusanthrax也提到)。将其保留在反应组件中:

shouldComponentUpdate(nextProps, nextState) {
  return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState);
}

在此使用lodash中的isEqual,请确保包含它。 这只会在道具或州值发生变化时重新渲染您的组件。

安装lodash:

npm install -S lodash

并在组件文件中导入isEqual:

import isEqual from 'lodash/isEqual';