3
\$\begingroup\$

I'm struggling to make a React/JS map I have more efficient. Essentially, I have a list of cards, and then a map of markers. When I hover on one of the cards, it changes the styling of the marker.

Here’s what it looks like:

enter image description here

But the way I'm doing this...I'm pretty sure is really inefficient, so here's how I have it setup in a couple of components:

//LocationsGrid.js
class LocationsGrid extends React.Component {
  state = {
    hoveredCardId: ""
  };

  setCardMarkerHover = location => {
    this.setState({
      hoveredCardId: location.pageid
    });
  };

  resetCardMarkerHover = () => {
    this.setState({
      hoveredCardId: ""
    });
  };

render() {
    const { locations } = this.props;

{locations.map((location, index) => (
    <LocationCard
      setCardMarkerHover={this.setCardMarkerHover}
      resetCardMarkerHover={this.resetCardMarkerHover}
      location={location}
    />
 ))}
   // map stuff
    <div className={classes.mapDiv}>
          <MapAndMarkers
            locations={locations}
            hoveredCardId={this.state.hoveredCardId}
          />
        </div>


//LocationCard.js
class LocationCard extends React.Component {
  render() {
    const { classes, location } = this.props;

    return (
      <Card
        className={classes.card}
        onMouseEnter={e => this.props.setCardMarkerHover(location)}
        onMouseLeave={e => this.props.resetCardMarkerHover()}
       >
        <CardContent className={classes.cardContentArea}>

        </CardContent>
      </Card>
    );
  }
}

// MapAndMarkers.js

class MapAndMarkers extends React.Component {
  render() {
    const { locations, hoveredCardId, pageid } = this.props;

    let MapMarkers = locations.map((location, index) => {
      return (
        <MapMarker
          key={location.id}
          lat={location.lat}
          lng={location.lng}
          pageid={location.pageid}
          hoveredCardId={hoveredCardId}
        />
      );
    });

    return (
      <div>
        <GoogleMapReact>
          {MapMarkers}
        </GoogleMapReact>
      </div>
    );
  }
}

// MapMarker.js
import classNames from 'classnames';
class MapMarker extends React.Component {
  render() {
    const { classes, pageid, hoveredCardId } = this.props;

    return (
      <div className={classes.markerParent}>

      <span className={classNames(classes.tooltips_span, pageid == hoveredCardId && classes.niftyHoverBackground)}>{this.props.name}</span>

      </div>
    );
  }
}

The problem with doing it this way is I'm pretty sure there's a whole bunch of wasted rendering. When I pulled out the mouse events from my LocationCard, everything else runs faster.

What would be a more efficient way of tracking hovered list items so that I can change the map marker style?

GitHub

Demo

\$\endgroup\$
1
\$\begingroup\$

While I wouldn't say your code is inefficiently styled, you can definitely improve the performance of your components.

React performs in a tree format, when a component updates, all their children will attempt to update and potentially re-render. This is part of what React calls the Reconciliation process.

There is a function you can add to your component classes called componentShouldUpdate, which comes with parameters (nextProps, nextState). The idea of this function is to decide whether the component needs to re-render. You can find some more information on this property here.

For example, if you were to hover and change the colour of one of the markers, the entire list of markers rerenders, but, you can make a check to see whether the specific marker is the one you want to color and so needs to be updated.

These kinds of stops on rerendering means as high as possible in your render trees means you can get the most performance gains.

shouldComponentUpdate(nextProps) { // inside MapMarker.js
    const { props } = this;
    return props.hoveredCardId !== nextProps.hoveredCardId
      || nextProps.hoveredCardId !== props.pageid;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ This is a helpful tip. I'll look more into that lifecycle method \$\endgroup\$ – Kyle Pennell Dec 19 '18 at 20:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.