反应:与事件侦听器关联的批处理状态更新

时间:2018-12-05 04:53:30

标签: javascript reactjs

我有一个带有'mouseover'和'mouseout'事件监听器的组件。在浏览器中,多个相同的组件彼此相邻(或重叠)渲染,因此可以按顺序触发“ mouseover”,“ mouseout”和另一个“ mouseover”事件(如果您悬停,从一个元素到另一个元素)

该组件在所有这些实例中都设置状态,但是我想知道是否没有一种更有效的方式来执行此操作,从而避免一次又一次发生三个状态更新。

我是在这里尝试不必要地优化吗,还是这是一个有效的问题?这是我的意思的例子。在这种情况下,我只是更新一个计数,但可以说我正在做一些更昂贵的事情,例如遍历数组。

(免责声明,我没有在此处使用新的代码插入,并且在运行此代码段时遇到了麻烦)。

import React, { Component } from 'react';

class DummyComponent extends Component {
  state = {
    someProp: 1
  };
  
  componentDidMount() {
    this.addEventListener('mouseover', this.handleEvent);
    this.addEventListener('mouseout', this.handleEvent);
  }
  
  componentWillUnmount() {
    this.removeEventListener('mouseover', this.handleEvent);
    this.removeEventListener('mouseout', this.handleEvent);
  }
  
  handleEvent(event) {
    console.log(event.type);
    this.setState({ someProp: this.state.someProp += 1 });
  };
  
  render() {
    return (
      <section>
        {this.state.someProp}
      </section>
    )
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

1 个答案:

答案 0 :(得分:1)

是否需要立即处理事件?如果不是,则似乎是一个很好的用例,用于取消处理处理程序方法,以使其调用时间不超过 X 毫秒(例如100毫秒)。这样做的不利之处在于,处理程序将至少等待那么长时间才能首次触发。

Lodash库提供了debounce的实现。

下面是如何修改代码以使用它:

import React, { Component } from 'react';
import _ from 'lodash';

class DummyComponent extends Component {
  state = {
    someProp: 1
  };

  componentDidMount() {
    this.addEventListener('mouseover', this.debouncedHandleEvent);
    this.addEventListener('mouseout', this.debouncedHandleEvent);
  }

  componentWillUnmount() {
    this.removeEventListener('mouseover', this.debouncedHandleEvent);
    this.removeEventListener('mouseout', this.debouncedHandleEvent);
  }

  handleEvent(event) {
    console.log(event.type);
    this.setState({ someProp: this.state.someProp += 1 });
  };

  // Debounced handler with a wait time of 100ms
  debouncedHandleEvent = _.debounce(handleEvent, 100)

  render() {
    return (
      <section>
        {this.state.someProp}
      </section>
    )
  }
}