react-google-maps: Uncaught TypeError: Cannot read property 'overlayMouseTarget' of null

I previously posted this on StackOverflow but since this is less of a “how to” question and more a case of “there might be a bug with the Overlay component”, I decided to repost it here.

When leaving the page that has the map with some OverlayView’s, I get the error message:

Uncaught TypeError: Cannot read property ‘overlayMouseTarget’ of null

Here is the code with the GoogleMap component:

const GMap = withGoogleMap((props) => (
  <GoogleMap
    ref={props.onMapMounted}
    defaultZoom={12}
    zoom={props.zoom}
    onDragEnd={props.onZoomChanged}
    onZoomChanged={props.onZoomChanged}
    defaultCenter={props.defaultCenter}
    center={props.center}
  >
    {
      props.markers && props.markers.map((data, index) => (
        <OverlayView
          key={index}
          position={{
            lat: data.get('loc').get('geo').get('lat'),
            lng: data.get('loc').get('geo').get('lng'),
          }}
          mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
          getPixelPositionOffset={(width, height) => ({ x: -(width / 2), y: -(height) })}
        >
          <WnmMarker
            text={data.get('text')}
            highlight={data.get('highlight')}
          />
        </OverlayView>
      ))
    }
  </GoogleMap>
));

Could it be that something is missing in the componentWillUnmount?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 24 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Taking @foloinfo’s advice, I implemented the following class in my project that eliminates the errors. Hopefully this will help somebody else, too!

import React from 'react';
import ReactDOM from 'react-dom';
import invariant from 'invariant';
import { OverlayView } from 'react-google-maps';
import { OVERLAY_VIEW } from 'react-google-maps/lib/constants';

export default class CustomOverlayView extends OverlayView {
  // Override draw function to catch errors with map panes being undefined to prevent console errors
  draw() {
    const { mapPaneName } = this.props;
    invariant(
      !!mapPaneName,
      `OverlayView requires either props.mapPaneName or props.defaultMapPaneName but got %s`,
      mapPaneName
    );
    // https://developers.google.com/maps/documentation/javascript/3.exp/reference#MapPanes
    const mapPanes = this.state[OVERLAY_VIEW].getPanes();
    if (mapPanes && this.containerElement) { // <-- Add conditional to ensure panes and container exist before drawing
      mapPanes[mapPaneName].appendChild(this.containerElement);

      ReactDOM.unstable_renderSubtreeIntoContainer(
        this,
        React.Children.only(this.props.children),
        this.containerElement,
        this.onPositionElement
      );
    }
  }
}

If it can help, after reading #405 , I added key={Math.random()} to <OverlayView /> and the error message disappeared.

I’m not sure if this is related but the width and height passed down to getPixelPositionOffset is sometimes wrong. I receive (0px, 13px) whereas my markers are (24px, 32px). It leads to a misplaced overlay on the map.


Here is the code with the GoogleMap component

      <GoogleMap ref={this.handleMapRef} {...this.optionalProps}
        defaultCenter={defaultCenter} defaultOptions={defaultOptions} defaultZoom={defaultZoom}
        onDragStart={this.handleDragStart} onIdle={this.handleIdle}>
        {this._selectedMarker && (
          <OverlayView /***** --> key={Math.random()} <-- *****/ position={{ lat, lng }}
            getPixelPositionOffset={this.getPixelPositionOffset}
            defaultMapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}>
            <img src={getMarkerIcon(poiType, true)} />
          </OverlayView>
        )}
        <MarkerClusterer onMarkerClick={this.handleMarkerClick} />
      </GoogleMap>

It seems like still an issue since it happens on 9.0.1. Adding key to OverlayView or wait till component to be mounted, didn’t work for me.

I could avoid by adding existence check before drawing of OverlayVIew like below.

  draw() {
    const { mapPaneName } = this.props
    invariant(
      !!mapPaneName,
      `OverlayView requires either props.mapPaneName or props.defaultMapPaneName but got %s`,
      mapPaneName
    )
    // https://developers.google.com/maps/documentation/javascript/3.exp/reference#MapPanes
    const mapPanes = this.state[OVERLAY_VIEW].getPanes()
    if(mapPanes){
      mapPanes[mapPaneName].appendChild(this.containerElement)

      ReactDOM.unstable_renderSubtreeIntoContainer(
        this,
        React.Children.only(this.props.children),
        this.containerElement,
        this.onPositionElement
      )
    }
  }

However I’m not sure it’s a correct way to fix it. Any suggestions?

Added: In some cases I needed to make sure this.containerElement exists as well, so modified to if(mapPanes && this.containerElement)

Here’s my solution:

The error (at least for me) is pretty benign and it only shows up once when the OverlayView is first attempted to be rendered. With that in mind, I tried delaying its render until after the rest of the Google Map is mounted. So essentially, you’re allowing the map some time to load before adding the Overlay. Bonus, no need to add a key at all.

class Map extends Component {
  constructor () {
    super()
    this.state = {
      loaded: false
    }
  }
  componentDidMount () {
    this.setState({ loaded: true })
  }

  render () {
    return (
      <GoogleMap>
        {this.state.loaded &&
          <OverlayView
            position={this.props.center}
            mapPaneName={OverlayView.OVERLAY_LAYER}
            getPixelPositionOffset={getPixelPositionOffset}
          >
            <div>My Overlay</div>
          </OverlayView> }
      </GoogleMap>
    )
  }
}

@joaoreynolds This repo is unmaintained more than a year, please refer to npm @react-google-maps/api

We have docs, examples and community.

I was getting an error when removing overlays (see below) so I also had to override onRemove in @owap 's solution. — Super Hack

  onRemove() {
    if (this.containerElement) {
      return super.onRemove();
    }
  }

The error was

Uncaught TypeError: Cannot read property 'parentNode' of undefined
    at CustomOverlayView.onRemove (OverlayView.js:184)

Sorry, I haven’t had the time to figure it out.

We use redux with several stores that each have an Immutable.List() of markers. When the user changes to a different section of our site we provide the map with data from the store corresponding to the given section of the site. Each Section of markers updates via callback that dispatches updates from a socket connection. Updates seem to be fine, but when we switch to a different stores marker List() is when it seems to choke.