【问题标题】:Using setTimeout to avoid re-renders in React在 React 中使用 setTimeout 避免重新渲染
【发布时间】:2018-03-05 17:19:28
【问题描述】:

有一个我经常使用的模式,我觉得它一定是一个反模式,但我不知道更好的替代方案。

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

 _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 并且我有多个元素同时更改它们的可见性时,我不想为每个元素重新渲染,而是只想要一个重新-在收到所有更新后渲染。

还有其他更好的方法来处理多个调用吗?

顺便说一句:如果您要使用上述技巧,请不要忘记在您的 componentWillUnmount 中调用 clearTimout(this._updateQueued)

【问题讨论】:

  • 实现去抖动
  • 使用去抖动实际上与上面相同。在引擎盖下,去抖动正在使用 setTimeout
  • 请查看shouldComponentUpdate(nextProps, nextState) {return true or false;}
  • @fungusanthrax 我看不出这有什么帮助?
  • 如果问题在于获取组件以防止重新渲染,这绝对是您想要采取的路线。您能否提供更多关于这不相关的信息?

标签: reactjs settimeout anti-patterns


【解决方案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();
}

【讨论】:

  • 是的,很可能是@JackAllan,除了更标准化一点,大多数 React 开发人员都知道什么是去抖动。
  • 使用去抖动器来减少重新渲染并不是一种反模式;事实上,这是一种常见的策略来处理您经常遇到的受控输入的迟缓问题,仅举一个例子。
【解决方案2】:

您可以使用这种生命周期方法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';

【讨论】:

  • @JackAllan 有帮助吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
  • 2020-12-13
  • 2016-12-06
相关资源
最近更新 更多