React and Google Maps: Binding events to an InfoWindow

Using React with Redux and Google Maps together introduces a host of challenges. There are several packages available for joining them together, but for a recent project I found neither of them met my needs, although they ended up being good guides.

One of the issues is that InfoWindows support an api that takes an HTML string to produce the inner content of the window. For static HTML, this is fine, and the google-maps-react package simply takes any children supplied to its own InfoWindow class and renders them using react-dom/Server's renderToString method. Like so:

1
2
3
4
5
6
7
8
9
updateContent() {
    const content = this.renderChildren();
    this.infowindow.setContent(content);
}

renderChildren() {
    const {children} = this.props;
    return ReactDOMServer.renderToString(children);
}

The problem with this is that if the children have any events, they won't be preserved. For instance, if your JSX looks like this

1
2
3
<InfoWindow>
    <div onClick={() => console.log('clicked') }>click me</div>
</InfoWindow>

your click handler will never fire.

In my own InfoWindow component class, I dealt with this by relying on React.render instead of ReactDOMServer.renderToString, by only rendering a wrapper div into Google's InfoWindow object and then using that as the container for render.

1
2
3
4
5
this.infoWindow = new google.maps.InfoWindow({
    content: '<div id="info-window-wrapper"></div>'
});

ReactDOM.render(<InfoWindowContents />, document.getElementById('info-window-wrapper'));

Obviously, this is still not ideal--You may want to randomize your id attribute or reference the dom in another way--but this is the best way I've found to deal with this problem.

2017-08-09