-
-
Save jgimbel/6a36d60e28aaf453d0093ddc47f36533 to your computer and use it in GitHub Desktop.
//Example Usage of custom control | |
export default ({lat, lng, google}) => ( | |
<GoogleMap | |
defaultCenter={{lat, lng}} | |
defaultZoom={14} | |
minZoom={6} | |
google={google} | |
containerStyle={{ height: '575px', width: '100%', position: 'relative' }} | |
> | |
<Marker position={{lat, lng}} /> | |
<MapControl position={google.maps.ControlPosition.BOTTOM_CENTER}> | |
<div>That was easy</div> | |
</MapControl> | |
</GoogleMap> | |
) |
import { Component } from 'react' | |
import { createPortal } from 'react-dom' | |
import { MAP } from 'react-google-maps/lib/constants' | |
import PropTypes from 'prop-types' | |
export default class MapControl extends Component { | |
static contextTypes = { [MAP]: PropTypes.object } | |
componentWillMount() { | |
this.map = this.context[MAP] | |
this.controlDiv = document.createElement('div') | |
this.map.controls[this.props.position].push(this.controlDiv) | |
} | |
componentWillUnmount() { | |
this.map.controls[this.props.position].removeAt(this.divIndex) | |
} | |
render() { | |
return createPortal(this.props.children, this.controlDiv) | |
} | |
} |
See https://github.com/tomchentw/react-google-maps/blob/master/src/components/InfoWindow.jsx#L142 for example use of ReactDOM.unstable_renderSubtreeIntoContainer
Hi all, I'm trying to implement this example but I cant understand the google prop on Map.js
. Can anyone explain me?
Thank you in advance
In this example this.divIndex
is undefined which throws an error on componentWillUnmount
. This should fix it.
componentWillMount() {
this.map = this.context[MAP];
this.controlDiv = document.createElement('div');
this.divIndex = this.map.controls[this.props.position].length;
this.map.controls[this.props.position].push(this.controlDiv);
}
Because componentWillMount isn't recommend for new version. I move it to constructor, leave it here for anyone need.
import { Component } from 'react';
import { createPortal } from 'react-dom';
import { MAP } from 'react-google-maps/lib/constants';
import { string, element, object, oneOfType, array } from 'prop-types';
/**
* This Component for add custom control to map
* (map.controls[position].push(component))
* NOTE:
* Can ref to map through context in constructor (or this.context expect contructor)
* User constructor to add div and render will createPortal
*/
export default class MapControl extends Component {
static propTypes = {
position: string.isRequired,
children: oneOfType([element, array]),
className: string,
};
static defaultProps = {
children: [],
className: '',
};
static contextTypes = { [MAP]: object };
constructor(props, context) {
super(props);
this.map = context[MAP];
this.controlDiv = document.createElement('div');
this.divIndex = this.map.controls[this.props.position].length;
this.map.controls[props.position].push(this.controlDiv);
}
componentWillUnmount() {
this.map.controls[this.props.position].removeAt(this.divIndex);
}
render() {
const { className } = this.props;
className && this.controlDiv.classList.add(className);
return createPortal(this.props.children, this.controlDiv);
}
}
For any other confused travelers, react-google-maps
uses React's Legacy Context API instead of the current one. This was relevant for me because I was trying to get this done in a functional component. So my code looks roughly like:
const MapControl = (props, context) => {
const map = context[MAP]
return null;
//whatever
}
MapControl.contextTypes = {
[MAP]: Proptypes.object,
};
Please note that the 16.3 release of React deprecated this API, although it will be included in all 16.x releases.
react-google-maps
hasn't been updated in a year. Not sure if it's still being maintained.
My completed component (using React 16.8 Hooks, but using the deprecated-in-16.3 Legacy Context) looks like this:
import React, { useEffect } from 'react';
import { createPortal } from 'react-dom';
import { MAP } from 'react-google-maps/lib/constants';
import PropTypes from 'prop-types';
export default function CustomDrawingManagerControl(
{ position = window.google.maps.ControlPosition.TOP_LEFT, children },
context
) {
const map = context[MAP];
const controlDiv = document.createElement('div');
useEffect(() => {
const controls = map.controls[position];
const index = controls.length;
controls.push(controlDiv);
return () => {
controls.removeAt(index);
};
});
return createPortal(
<div style={{ marginLeft: 16, marginTop: 16 }}>{children}</div>,
controlDiv
);
}
CustomDrawingManagerControl.contextTypes = {
[MAP]: PropTypes.object,
};
To be used like this:
<GoogleMap {...props}>
<CustomMapControl position={google.maps.ControlPosition.BOTTOM_CENTER}>
<div>That was easy</div>
</CustomMapControl>
</GoogleMap>
Implemented above example It gives an error.
Cannot read property 'ControlPosition' of undefined
Can I know what is wrong with this?
<MapControl position={google.maps.ControlPosition.BOTTOM_CENTER}> <div>That was easy</div> </MapControl>
Implemented above example It gives an error.
Cannot read property 'ControlPosition' of undefined
Can I know what is wrong with this?
<MapControl position={google.maps.ControlPosition.BOTTOM_CENTER}> <div>That was easy</div> </MapControl>
maybe you can try replace google
to window.google
;
or replace google.maps.ControlPosition.BOTTOM_CENTER
to 11
(not recommended)
Wrap the map component with the withScript
HOC so the maps library is loaded.
With this solution, my control was "blinking" every time the map re-rendered, but this didn't happen when I used this solution instead.
getting this error while trying to use the above code using ReacDOM.render
_renderNewRootComponent(): Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate.