0

I have a component with 'mouseover' and 'mouseout' event listeners. Several of this same component render next to one another (or overlap) in the browser, so it's possible to fire a 'mouseover', 'mouseout' and then another 'mouseover' event in that order (if you're hovering over from one element to the next).

The component sets state in all of those instances, but I'm wondering if there isn't a more efficient way of going about this, so as to avoid three state updates happening one after another.

Am I trying to unnecessarily optimize here or is this a valid concern? Here's an example of what I mean. In this case I'm just updating a count, but let's say I'm doing something more expensive like iterating over an array.

(Disclaimer, I haven't used the new code insertion on here and I'm having trouble running this snippet).

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>
Jose
  • 4,880
  • 8
  • 27
  • 49
  • https://stackoverflow.com/questions/42038590/when-to-use-react-setstate-callback – Robert Mennell Dec 05 '18 at 04:59
  • 1
    Possible duplicate of [When to use React setState callback](https://stackoverflow.com/questions/42038590/when-to-use-react-setstate-callback) – Robert Mennell Dec 05 '18 at 05:00
  • Is it necessary that the event get handled immediately? If not, it seems like a good use case for debouncing the handling so that it doesn't happen more frequently than say 100ms: https://lodash.com/docs/#debounce ... downside is that the handler will wait at least that long before firing the first time. – Daniel Bank Dec 05 '18 at 05:04
  • @DanielBank There is some UI dependent on state updating, but you might be right. 100ms might be just enough of a delay. – Jose Dec 05 '18 at 05:08

1 Answers1

1

Is it necessary that the event get handled immediately? If not, it seems like a good use case for debouncing the handler method so that it is not invoked more frequently than X milliseconds (e.g. 100ms). The downside of this is that the handler will wait at least that long before firing the first time.

The Lodash library provides an implementation of debounce.

Below is how your code could be modified to use it:

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>
    )
  }
}
Daniel Bank
  • 3,581
  • 3
  • 39
  • 50