Pass back coordinates to display in react-google-maps - javascript

Below is my code:
const SiteGoogleMap = compose(
withProps({
googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAP_API_KEY}&v=3.exp&libraries=geometry,drawing,places`,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />
}),
withScriptjs,
withGoogleMap
)((props) =>
<GoogleMap
defaultZoom={18}
defaultCenter={{ lat: 3.1314067, lng: 101.6285082 }}
>
{props.isMarkerShown && <Marker position={{ lat: -34.397, lng: 150.644
}} onClick={props.onMarkerClick} />}
<DrawingManager
defaultDrawingMode={google.maps.drawing.OverlayType.POLYGON}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON
],
}
}}
/>
<Polygon path={coordinates} />
</GoogleMap>
)
I would like to get the coordinates (polygon path) from my server. Below is what I have done to get it. It is a component:
export default class Map extends Component {
state = {
isMarkerShown: false,
coordinates: []
}
componentDidMount() {
this.fetchBoundaries()
}
render () {
const { coordinates } = this.state
return (
<SiteGoogleMap
isMarkerShown={this.state.isMarkerShown}
onMarkerClick={this.handleMarkerClick}
/>
);
}
async fetchBoundaries () {
try {
const { coordinates } = this.state
const item = await service.getBoundaries('59d850878328bd177bf50b4d')
coordinates = item.boundaries
this.setState({ coordinates })
} catch (e) {
notification.show('error', 'Unable to load successfully', 'Unable to load client successfully. Please try again later.')
}
}
}
From the fetchBoundaries() function, I am able to get my coordinates. But, it just can't pass it to <Polygon path={coordinates} /> for display.
Anyone know what went wrong?

Related

React Google Maps unique key error in loop

I got this react-google-maps component it is working and I receive all the data from the different locations but the console gives me this error message:
Warning: Each child in a list should have a unique "key" prop.
In my component, I've added a unique key tho.. what's the problem?
I import the map component on the page simply like that <Map />.
import React from 'react'
import { GoogleMap, Marker, withGoogleMap, withScriptjs, InfoWindow } from "react-google-maps"
import { useStaticQuery, graphql } from "gatsby"
const Map = () => {
const data = useStaticQuery(graphql`
{
allContentfulHotels {
nodes {
id
title
location {
lat
lon
}
}
}
}
`)
const {
allContentfulHotels: { nodes: locations },
} = data
return (
<>
{locations.map(({ location }) => {
console.log(location);
return (
<GoogleMap
key={location.id}
defaultZoom={15}
defaultCenter={{
lat: location.lat,
lng: location.lon,
}}
>
<Marker
key={location.id}
position={{
lat: location.lat,
lng: location.lon,
}}
>
</Marker>
</GoogleMap>
)
})}
</>
)
}
const MapComponent = withScriptjs(withGoogleMap(Map));
const MyMap = () => (
<div>
<div
style={{ width: '100%' }}
>
<MapComponent
isMarkerShown
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `500px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
</div>
)
export default MyMap
Hope someone knows what the problem is.
For Example: I am Using map function as below and set unique key..
{locations.map(({ location }, index) => {
console.log(location);
console.log(index);
return (
<GoogleMap
key={index}
defaultZoom={15}
defaultCenter={{
lat: location.lat,
lng: location.lon,
}}
Looks like you're specifying the same key for <GoogleMap /> and <Marker /> component, try setting different keys for components:
<GoogleMap
key={`map-${location.id}`}
defaultZoom={15}
defaultCenter={{
lat: location.lat,
lng: location.lon,
}}
>
<Marker
key={`marker-${location.id}`}
position={{
lat: location.lat,
lng: location.lon,
}}
>
</Marker>
</GoogleMap>

add a route, google is unedfined

I try to add a simple route in my map but when i call google.maps.DirectionsService() i get this google is undefined, so i try to add a const variable but now the error message is Cannot read property 'maps' of undefined..
I don't know what im doing wrong
const google = window.google;
class Map extends Component {
constructor(props) {
super(props);
this.state = {
latitude: 0,
longitude: 0,
nombre_de_bars: null
}
}
map() {
const [selectedBar, setSelectedBar] = useState(null);
const { nombre_de_bars } = this.state
const rows = nombre_de_bars.map(bar =>
<Marker key={bar._id}
position={{
lat: bar.latitude,
lng: bar.longitude
}}
onClick={() => {
setSelectedBar(bar);
}}
icon={{
url: '/images/biere_logo.png',
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
);
return (
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: this.state.latitude, lng: this.state.longitude }}
defaultOptions={{
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false
}}>
<Marker
position={{ lat: this.state.latitude, lng: this.state.longitude }}
icon={{
url: '/images/marker.png',
scaledSize: new window.google.maps.Size(50, 50)
}}
/>
{rows}
{selectedBar && (
<InfoWindow
position={{
lat: selectedBar.latitude,
lng: selectedBar.longitude
}}
onCloseClick={() => {
setSelectedBar(null);
}}
>
<div>
<p>{selectedBar.name}</p>
<p>{selectedBar.description}</p>
<button onClick={() => {
this.itineraireTo(selectedBar);
}}>Je m'y rend</button>
</div>
</InfoWindow>
)}
</GoogleMap>
);
}
render() {
const WrappedMap = withScriptjs(withGoogleMap(this.map.bind(this)));
const DirectionsService = new google.maps.DirectionsService();
return (
<WrappedMap
googleMapURL="https://maps.googleapis.com/maps/api/js?key=MY_KEY&v=3.exp&libraries=geometry,drawing,places"
loadingElement={<div style={{ height: `100%`, width: '100%' }} />}
containerElement={<div style={{ height: `100%`, width: '100%' }} />}
mapElement={<div style={{ height: `100%`, width: '100%' }} />}
/>
);
}
}
export default Map;
I try to export with withGoogleMap(Map) but not fix the problem.
I read the documentation on tomchentw.github.io but not the similar problem was occured

When displaying multiple markers on a map, how to open just one info window, when clicking on a marker?

I'm using react-google-maps to display a map with markers, and when you click on a marker, all the info windows open up. I would like to display only one marker's info window when I click on it, and for the others to stay closed.
Here is my code:
<GoogleMap
defaultZoom={15}
defaultCenter={{ lat: 51.508530, lng: -0.076132 }}
>
{props.places && props.places.map((place, i) =>
<Marker onClick={props.onToggleOpen} key={i} position={{ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }} >
{props.isOpen && <InfoWindow onCloseClick={props.onToggleOpen}>
<div>{place.name}</div>
</InfoWindow>}
</Marker>
)}
</GoogleMap>
And I'm opening and closing the InfoWindow with this
import { compose, withProps, withStateHandlers, withHandlers, withState } from "recompose";
...
withStateHandlers(() => ({
isOpen: false,
}), {
onToggleOpen: ({ isOpen, id }) => () => ({
isOpen: !isOpen,
})
}),
I'm mapping over all the markers, and displaying them on the map. How could I click open just one marker InfoWindow?
Here is a related question, but it's not made with React, and doesn't use the react-google-maps.
It's more of a React question. You can pass the index of a clicked Marker to onToggleOpen and instead of isOpen you use a selectedPlace state that holds the index of a clicked Marker and use this index to render the right InfoWindow.
Here is an example (not fully tested, but you can get the idea):
/*global google*/
import React from "react"
import { compose, withProps, withHandlers, withState, withStateHandlers } from "recompose"
import { withScriptjs, withGoogleMap, GoogleMap, Marker, InfoWindow } from "react-google-maps"
const MyMapComponent = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap,
withState('places', 'updatePlaces', ''),
withState('selectedPlace', 'updateSelectedPlace', null),
withHandlers(() => {
const refs = {
map: undefined,
}
return {
onMapMounted: () => ref => {
refs.map = ref
},
fetchPlaces: ({ updatePlaces }) => {
let places;
const bounds = refs.map.getBounds();
const service = new google.maps.places.PlacesService(refs.map.context.__SECRET_MAP_DO_NOT_USE_OR_YOU_WILL_BE_FIRED);
const request = {
bounds: bounds,
type: ['hotel']
};
service.nearbySearch(request, (results, status) => {
if (status == google.maps.places.PlacesServiceStatus.OK) {
console.log(results);
updatePlaces(results);
}
})
},
onToggleOpen: ({ updateSelectedPlace }) => key => {
updateSelectedPlace(key);
}
}
}),
)((props) => {
console.log(props);
return (
<GoogleMap
onTilesLoaded={props.fetchPlaces}
ref={props.onMapMounted}
onBoundsChanged={props.fetchPlaces}
defaultZoom={15}
defaultCenter={{ lat: 51.508530, lng: -0.076132 }}
>
{props.places && props.places.map((place, i) =>
<Marker onClick={() => props.onToggleOpen(i)} key={i} position={{ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }}>
{props.selectedPlace === i && <InfoWindow onCloseClick={props.onToggleOpen}>
<div>
{props.places[props.selectedPlace].name}
</div>
</InfoWindow>}
</Marker>
)}
</GoogleMap>
)
})
export default class MyFancyComponent extends React.PureComponent {
render() {
return (
<MyMapComponent />
)
}
}

Limiting users to one polygon at a time with Google Maps

I have a React-Google-Maps component which allows users to draw polygons and passes those polygons' associated GeoJSON up to the parent component through a callback.
What I would like to do is to limit users to one polygon at a time; meaning, when a user completes a polygon, all previously rendered polygons are deleted.
I've seen some examples on how to do this with vanilla JS, jQuery and Angular 2, but nothing on React.
My component:
import React, { Component } from 'react';
const { compose, withProps } = require('recompose');
const { withScriptjs, withGoogleMap, GoogleMap } = require('react-google-maps');
const {
DrawingManager
} = require('react-google-maps/lib/components/drawing/DrawingManager');
const editTrack = polygon => {
let GeoJSON = {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: []
},
properties: {}
};
for (let point of polygon.getPath().getArray()) {
GeoJSON.geometry.coordinates.push([point.lng(), point.lat()]);
}
return GeoJSON;
};
const PlotMap = compose(
withProps({
googleMapURL:
'https://maps.googleapis.com/maps/api/js?key=mykey&v=3.exp&libraries=geometry,drawing,places',
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />
}),
withScriptjs,
withGoogleMap
)(props => (
<GoogleMap
defaultZoom={8}
defaultCenter={new google.maps.LatLng(32.095, 35.398)}>
<DrawingManager
onPolygonComplete={polygon => {
polygon.setEditable(true);
props.getGeoJSON(editTrack(polygon));
google.maps.event.addListener(polygon.getPath(), 'insert_at', function(
index,
obj
) {
props.getGeoJSON(editTrack(polygon));
});
google.maps.event.addListener(polygon.getPath(), 'set_at', function(
index,
obj
) {
props.getGeoJSON(editTrack(polygon));
});
}}
defaultDrawingMode={google.maps.drawing.OverlayType.POLYGON}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.POLYGON]
}
}}
/>
</GoogleMap>
));
export default PlotMap;
OK, got it.
import React, { Component } from 'react';
const { compose, withProps } = require('recompose');
const { withScriptjs, withGoogleMap, GoogleMap } = require('react-google-maps');
const {
DrawingManager
} = require('react-google-maps/lib/components/drawing/DrawingManager');
const editTrack = polygon => {
let GeoJSON = {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[]]
},
properties: {}
};
for (let point of polygon.getPath().getArray()) {
GeoJSON.geometry.coordinates[0].push([point.lng(), point.lat()]);
}
GeoJSON.geometry.coordinates[0].push(GeoJSON.geometry.coordinates[0][0]);
return GeoJSON;
};
//this is where we will keep our polygon when it is drawn
let latestPolygon;
const PlotMap = compose(
withProps({
googleMapURL:
'https://maps.googleapis.com/maps/api/js?key=mykey&v=3.exp&libraries=geometry,drawing,places',
loadingElement: <div style={{ height: `100%`, width: `100%` }} />,
containerElement: <div style={{ height: `400px`, width: `100%` }} />,
mapElement: <div style={{ height: `100%`, width: `100%` }} />
}),
withScriptjs,
withGoogleMap
)(props => (
<GoogleMap
defaultZoom={8}
defaultCenter={new google.maps.LatLng(32.095, 35.398)}>
<DrawingManager
onPolygonComplete={polygon => {
//if we have a polygon on the map, delete it now
latestPolygon && latestPolygon.setMap(null);
polygon.setEditable(true);
props.getGeoJSON(editTrack(polygon));
google.maps.event.addListener(polygon.getPath(), 'insert_at', function(
index,
obj
) {
props.getGeoJSON(editTrack(polygon));
});
google.maps.event.addListener(polygon.getPath(), 'set_at', function(
index,
obj
) {
props.getGeoJSON(editTrack(polygon));
});
//now we set the storage polygon to be the one we just drew
latestPolygon = polygon;
}}
defaultDrawingMode={google.maps.drawing.OverlayType.POLYGON}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.POLYGON]
}
}}
/>
</GoogleMap>
));
export default PlotMap;

How to do getPaths of polygon from the react-google-map?

Below is my coding:
const SiteGoogleMap = compose(
withProps({
googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAP_API_KEY}&v=3.exp&libraries=geometry,drawing,places`,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />
}),
withScriptjs,
withGoogleMap
)((props) =>
<GoogleMap
defaultZoom={18}
defaultCenter={{ lat: 3.1314067, lng: 101.6285082 }}
>
{props.isMarkerShown && <Marker position={{ lat: -34.397, lng: 150.644 }} onClick={props.onMarkerClick} />}
<DrawingManager
defaultDrawingMode={google.maps.drawing.OverlayType.POLYGON}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON
],
}
}}
onPolygonComplete={(value) => console.log(getPaths())}
/>
</GoogleMap>
I'm trying to get the path of the polygon drawn which will give me the coordinates of the paths. But it gives undefined on console.log. Do you guys know why?
Since onPolygonComplete event is mapped to polygoncomplete of DrawingManager class, the value parameter represents Polygon object:
onPolygonComplete={(value) => console.log(getPaths())}
^^^^^
polygon object
that could be passed into getPaths function:
onPolygonComplete={(value) => console.log(getPaths(value))}
and then the coordinates of the polygon drawn could be printed like this:
function getPaths(polygon){
var coordinates = (polygon.getPath().getArray());
console.log(coordinates);
}

Categories