React-leaflet-draw doesn't keep updated onCreated to a hook state of drawn features - reactjs

Context
I am trying to save my collection of my drawn features dynamically into a state hook, and keeping them updated from onCreated, onEdited and onDeleted.
This is how my UI looks like:
Problem
The issue happens when, I click on the trash icon and remove one of the created features with (let's say) id=2, and then create another new feature of id=3; it looks like the onCreated method doesn't have it's state of features updated, and when creating the feature of id 3, it returns to show the deleted figure of id 2 in the data (but not on the map).
This is how it looks like when the old figure is deleted, but when creating a new one, the onCreate makes it persistent in the data displayed at the right container.
This is the code that I run: (The featureCollection is the state hook passed from the App.js):
import { FeatureGroup } from "react-leaflet";
import { EditControl } from "react-leaflet-draw";
export default function EditFeature({ lkey, setlKey, featuresCollection, setFeaturesCollection }) {
const _onCreated = (e) => {
let layer = { id: e.layer._leaflet_id, ...e.layer.toGeoJSON() };
setlKey(e.layer._leaflet_id);
setFeaturesCollection({
...featuresCollection,
features: [layer, ...featuresCollection.features]
});
};
const _onDeleted = (e) => {
let unwanted = Object.keys(e.layers._layers);
unwanted = unwanted.map(item => Number(item));
// Filter out those layers whose id is in the unwanted array
let filtered = featuresCollection.features.filter(e => !unwanted.includes(e.id));
setFeaturesCollection({
...featuresCollection,
features: [...filtered]
});
};
return (
<FeatureGroup>
<EditControl
key={lkey}
id="EditControl"
onCreated={_onCreated}
onDeleted={_onDeleted}
position="topright"
draw={{
circle: false,
circlemarker: false,
polyline: false,
marker: false,
polygon: {
allowIntersection: false,
shapeOptions: {
color: "purple",
weight: 3
},
},
rectangle: {
shapeOptions: {
color: "purple",
weight: 3
}
}
}}
/>
</FeatureGroup>
);
};
My main goal is to achieve that my state keeps updated the figures shown in the map, in order to then export those to a geojson file, like the web GeoJSON.io does! (within React tho).
Reference:
https://github.com/alex3165/react-leaflet-draw/issues/154

Related

GoogleMaps api : why does my map state become null?

Help appreciated, I'm stuck !
What I try to do
I display a Google map with a set of marker.
When I click on a marker, I want to add a Google circle to the map.
What happens
When I click on a first marker, no circle is displayed.
But when I click on a second marker and more, they are displayed !
Why it does not work
I've tracked the map state value with console.log.
The problem is that when I first go to the MarkkerClicked function, for an unknown reason, the "map" state's value is "null" ! So no circle is created.
And, even stranger, the map state contains a map instance when the map is first loaded, and also when I click a second marker.
Can you tell me what I have done wrong, that makes the map value set to null when the first marker is clicked ?
My component :
import { GoogleMap, MarkerF, useJsApiLoader } from "#react-google-maps/api";
import Box from '#mui/material/Box';
import { useSelector } from 'react-redux'
let mapCircle1 = null
export default function MapPage() {
// The array of markers is in the REDUX store
const selectMarkersArray = state => state.markersArray
const markersArray = useSelector(selectMarkersArray)
// This state contains the selected marker (or null if no marker selected)
const [selectedMarker, setSelectedMarker] = useState(null);
// Options for GoogleMaps
let center = {
lat: 43.3318,
lng: 5.0550
}
let zoom = 15
const containerStyle = {
width: "100%",
height: "100%"
}
// GoogleMaps loading instructions
const { isLoaded } = useJsApiLoader({
id: 'google-map-script',
googleMapsApiKey: "MY-GOOGLE-KEY"
})
const [map, setMap] = useState(null)
const onLoad = useCallback(function callback(map) {
setMap(map)
console.log('map value in onLoad :')
console.log(map)
}, [])
const onUnmount = useCallback(function callback(map) {
setMap(null)
}, [])
// Function executed when a marker is clicked
function markerClicked(props) {
console.log('map value in markerClicked :')
console.log(map)
// I create a new Circle data
let circleOption1 = {
fillColor: "#2b32ac ",
map: map,
center: {lat:props.marker.spotLatitude, lng:props.marker.spotLongitude},
radius: props.marker.spotCircleRadius,
};
mapCircle1 = new window.google.maps.Circle(circleOption1);
// I update the selecte marker state
setSelectedMarker({...props.marker})
}
return (isLoaded ? (
<Box height="80vh" display="flex" flexDirection="column">
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
zoom={zoom}
onLoad={onLoad}
onUnmount={onUnmount}
>
{markersArray.map((marker, index) => {
return (
<MarkerF
key={index.toString()}
position={{lat:marker.spotLatitude, lng:marker.spotLongitude}}
onClick={() => markerClicked({marker:marker})}
>
</MarkerF>
)
})}
</GoogleMap>
</Box>
) : <></>
)
};
And the console.log (first log when the map is loaded, second when the first marker is clicked, third when another marker is clicked):
map value in onLoad :
jj {gm_bindings_: {…}, __gm: hda, gm_accessors_: {…}, mapCapabilities: {…}, renderingType: 'UNINITIALIZED', …}
map value in markerClicked :
null
map value in markerClicked :
jj {gm_bindings_: {…}, __gm: hda, gm_accessors_: {…}, mapCapabilities: {…}, renderingType: 'RASTER', …}```
It coulds be because you are not using State Hooks and the <Circle /> component for rendering / updating circles
I was able to reproduce your code on codesandbox and confirmed that the map is indeed returning null per marker click. I'm still unsure as to why it really is happening, but I managed to fix it and managed to render a circle even on the first marker click, after modifying your code by utilizing State Hooks for your circles, and also using the <Circle /> component as per the react-google-maps/api library docs.
I just managed to hardcode some stuff since I did not use redux to reproduce your code but one of the things I did is create a circles array State Hook:
// this array gets updated whenever you click on a marker
const [circles, setCircles] = useState([
{
id: "",
center: null,
circleOptions: {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
clickable: false,
draggable: false,
editable: false,
visible: true,
radius: 100,
zIndex: 1
}
}
]);
Just make sure to add the useState on your import.
Then for demonstration, I hardcoded a markers array:
// This could be your array of marker using redux,
// I just hardcoded this for demonstration
const markersArray = [
{
id: 1,
position: { lat: 43.333194, lng: 5.050184 }
},
{
id: 2,
position: { lat: 43.336356, lng: 5.053353 }
},
{
id: 3,
position: { lat: 43.331609, lng: 5.056403 }
},
{
id: 4,
position: { lat: 43.328806, lng: 5.058998 }
}
];
Then here's my markerClicked function looks like:
// Function executed when a marker is clicked
const markerClicked = (marker) => {
console.log("map value on marker click: ");
console.log(map);
// This stores the marker coordinates
// in which we will use for the center of your circle
const markerLatLng = marker.latLng.toJSON();
// this will update our circle array
// adding another object with different center
// the center is fetched from the marker that was clicked
setCircles((prevState) => {
return [
...prevState,
{
id: "",
center: markerLatLng,
circleOptions: {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
clickable: false,
draggable: false,
editable: false,
visible: true,
radius: 100,
zIndex: 1
}
}
];
});
// this is for you to see that the circles array is updated.
console.log(circles);
};
Please do note that the onClick attribute for <MarkerF /> automatically returns a parameter that includes the marker's coordinates and other stuff, you can just try to use console.log if you wanna check. Also make sure that the value you put on the onClick is equals to the name of the function alone. In this case, it is markerClicked, you'll see later on.
Note: I also added a mapClicked function for you to be able to clear the circles array.
Please see proof of concept sandbox below.
Then this is how I rendered the <GoogleMap /> component with <MarkerF /> and <Circle /> components as its children.
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
zoom={zoom}
onLoad={onLoad}
onUnmount={onUnmount}
onClick={mapClicked}
>
{markersArray.map((marker, index) => {
return (
<MarkerF
key={index.toString()}
position={{ lat: marker.position.lat, lng: marker.position.lng }}
onClick={markerClicked}
></MarkerF>
);
})}
{/* This maps through the circles array, so when the array gets updated,
another circle is added */}
{circles.map((circle, index) => {
return (
<Circle
key={index.toString()}
// required
center={circle.center}
// required
options={circle.circleOptions}
/>
);
})}
</GoogleMap>
With all these, the map value on marker click does not return null, and a circle gets rendered even on first marker click.
Here's a proof of concept sandbox for you to check and see how it works ( Make sure to use your own API key to test ): https://codesandbox.io/s/proof-of-concept-show-circle-on-marker-click-s175wl?file=/src/Map.js
Note: There's some weird offset between the marker and the circle if you zoom out too far, but seems fine when you zoom in. I have encountered this on some previous questions here in SO when rendering polylines and I don't know why is that or how to fix it.
With that said, hope this helps!

OpenLayers6 and React

I am trying to implement OpenLayers6 ("ol": "^6.14.1") into a ReactJS project, but all the documentation is created in normal JS files and I can't find any good examples or tutorials with functional components and OpenLayers6.
I have troubles figuring out how to implement the majority of things, because the docs seem to ignore the lifecycle of React.
What I've managed to do until now is to add a marker and a popup right above the marker; to close the popup and delete the marker by deleting the whole vector layer(which seems overkill).
import { useState, useEffect, useRef } from 'react';
// import ModalUI from '../UI/ModalUI';
import classes from './MapUI.module.css';
import { drawerActions } from '../../store/drawer-slice';
import 'ol/ol.css';
import { Map, View, Overlay, Feature } from 'ol';
import Point from 'ol/geom/Point';
import { Vector as VectorLayer } from 'ol/layer';
import VectorSource from 'ol/source/Vector';
import { fromLonLat, toLonLat } from 'ol/proj';
import { toStringHDMS } from 'ol/coordinate';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import PopUp from './PopUp';
import { useDispatch } from 'react-redux';
export default function MapUI() {
const mapRef = useRef();
const popup = useRef();
const [coordinates, setCoordinates] = useState('');
const [newMarker, setNewMarker] = useState(
new Feature({
geometry: new Point([[]]),
name: '',
})
);
const [newMarkersLayer, setNewMarkersLayer] = useState(
new VectorLayer({
properties: { name: 'newMarkers' },
source: new VectorSource({
features: [newMarker],
}),
})
);
const closePopup = () => {
map.getOverlayById('map-popup').setPosition(undefined);
map.removeLayer(newMarkersLayer);
};
const [map] = useState(
new Map({
target: '',
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
properties: { name: 'existingMarkers' },
source: new VectorSource({
// features: [marker],
}),
}),
],
view: new View({
center: fromLonLat([26.08, 44.46]),
zoom: 15,
minZoom: 10,
maxZoom: 20,
}),
})
);
useEffect(() => {
const overlay = new Overlay({
element: popup.current,
id: 'map-popup',
autoPan: {
animation: {
duration: 250,
},
},
});
// console.log('useEffect in MapUI.jsx');
map.addOverlay(overlay);
map.setTarget(mapRef.current);
map.on('singleclick', function (evt) {
map.addLayer(newMarkersLayer);
newMarker.getGeometry().setCoordinates(evt.coordinate);
setCoordinates(toStringHDMS(toLonLat(evt.coordinate)));
overlay.setPosition(evt.coordinate);
});
}, [map]);
return (
<>
<div
style={{ height: '100%', width: '100%' }}
ref={mapRef}
className='map-container'
/>
<div id='map-popup' className={classes['ol-popup']} ref={popup}>
<PopUp coordinates={coordinates} closePopup={closePopup} />
</div>
</>
);
}
The project in the end will have an array of markers that will be requested from a back-end and will populate the given map while also keeping the ability to add new markers to the map (and to the back-end).
The general issue that I face is with how all ol objects are used in the documentation. Everything is just created in a file using const and then operated upon.
But in React I have to use useEffect() and useState() and can't just create dependencies or manipulate state however the docs say.
I am looking for some guidelines on how to properly use OpenLayers6 in React. On this note I have some questions:
How can I remove a marker without removing the whole layer ?
How can I make a marker stay on the map ?
How can I render an array or markers on the map ?
Is it correct the way I use useState() to create the initial map ?
Is it correct the way I use useState() to keep the marker and the VectorLayer on which the marker will be placed ?
Try using this library, Rlayers
this was very helpfull for me to combine with another gis library, like turf and d3
How can I remove a marker without removing the whole layer ?
You can use react-query as hooks (useMutation) fuction to call inside useCallback
How can I make a marker stay on the map ?
What are you meaning about stay? is like show and not hide? just get state and put that's value into true
How can I render an array or markers on the map ?
again use react-query
Is it correct the way I use useState() to create the initial map ?
Yes if you have another map on your application
Is it correct the way I use useState() to keep the marker and the VectorLayer on which the marker will be placed ?
Yes
As you know, OpenLayers uses an imperative API where you add and remove features to layers, etc., while in React land, we generally do things declaratively. You'll need some imperative glue code that takes your React state and mutates the OpenLayers state to match what your React state is - that's what React itself does when it reconciles the DOM.
You can do that in a couple of different ways:
useEffects to do what useEffect does: imperative side effects (updating OL state) based on declarative inputs (React state); described below
The other option, used by e.g. react-leaflet, is that you describe the whole Leaflet state as React elements, and the library reconciles the Leaflet state based on that. It's a lot more work, but feels more React-y.
Here's a pair of custom hooks that make things a bit easier, loosely based on your example. It's in TypeScript, but if you need plain JS, just remove the TypeScript specific things (by e.g. running this through the typescriptlang.org transpiler).
useOpenLayersMap is a hook that sets up an OL Map in a ref and returns it, and takes care that a given container renders the map.
useOpenLayersMarkerSource is a hook that receives a list of marker data (here quite a limited definition, but you could amend it as you like), returns a VectorSource and also takes care that modifications to the list of marker data are reflected into the VectorSource as new Features.
Now, all the MapUI component needs to do is use those two hooks with valid initial data; it can modify its markerData state and the changes get reflected into the map.
import React, { useRef, useState } from "react";
import "ol/ol.css";
import { Feature, Map, View } from "ol";
import Point from "ol/geom/Point";
import { Vector as VectorLayer } from "ol/layer";
import VectorSource from "ol/source/Vector";
import { fromLonLat } from "ol/proj";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import { MapOptions } from "ol/PluggableMap";
interface MarkerDatum {
lat: number;
lon: number;
name: string;
}
function convertMarkerDataToFeatures(markerData: MarkerDatum[]) {
return markerData.map(
(md) =>
new Feature({
geometry: new Point(fromLonLat([md.lon, md.lat])),
name: md.name,
}),
);
}
const centerLat = 60.45242;
const centerLon = 22.27831;
function useOpenLayersMap(
mapDivRef: React.MutableRefObject<HTMLDivElement | null>,
getInitialOptions: () => Partial<MapOptions>,
) {
const mapRef = useRef<Map | null>(null);
React.useEffect(() => {
if (!mapRef.current) {
// markersSourceRef.current = new VectorSource();
mapRef.current = new Map({
target: mapDivRef.current ?? undefined,
...getInitialOptions(),
});
}
}, []);
React.useLayoutEffect(() => {
if (mapRef.current && mapDivRef.current) {
mapRef.current.setTarget(mapDivRef.current);
}
}, []);
return mapRef.current;
}
function useOpenLayersMarkerSource(markerData: MarkerDatum[]) {
const [markersSource] = useState(() => new VectorSource());
React.useEffect(() => {
// TODO: this would do better to only remove removed features,
// modify modified features and add new features
markersSource.clear(true);
markersSource.addFeatures(convertMarkerDataToFeatures(markerData));
}, [markerData]);
return markersSource;
}
export default function MapUI() {
const mapDivRef = useRef<HTMLDivElement>(null);
const [markerData, setMarkerData] = React.useState<MarkerDatum[]>([
{
lon: centerLon,
lat: centerLat,
name: "turku",
},
]);
const markerSource = useOpenLayersMarkerSource(markerData);
const map = useOpenLayersMap(mapDivRef, () => ({
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
properties: { name: "existingMarkers" },
source: markerSource,
}),
],
view: new View({
center: fromLonLat([centerLon, centerLat]),
zoom: 12,
minZoom: 12,
maxZoom: 20,
}),
}));
const addNewFeature = React.useCallback(() => {
setMarkerData((prevMarkerData) => [
...prevMarkerData,
{
lat: centerLat - 0.05 + Math.random() * 0.1,
lon: centerLon - 0.05 + Math.random() * 0.1,
name: "marker " + (0 | +new Date()).toString(36),
},
]);
}, []);
return (
<>
<button onClick={addNewFeature}>Add new feature</button>
<div
style={{ height: "800px", width: "800px" }}
ref={mapDivRef}
className="map-container"
/>
</>
);
}

Without setTimeout component is not rendering the proper data

This question is merely for curiosity. So, I have a parent component that fetches some data (Firebase) and saves that data in the state, and also passes the data to the child. The child's code is the following:
import { Bar, Doughnut } from 'react-chartjs-2'
import { Chart } from 'chart.js/auto'
import { useState, useEffect } from 'react'
import _ from 'lodash'
const initialData = {
labels: [],
datasets: [
{
id: 0,
data: [],
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#FF6384'],
color: ['#FF6384', '#36A2EB', '#FFCE56', '#FF6384'],
borderWidth: 0,
},
],
}
var config2 = {
maintainAspectRatio: true,
responsive: true,
}
export default function DoughnutChart(props) {
const [data, setData] = useState(initialData)
useEffect(() => {
const newData = _.cloneDeep(initialData)
var wins = 0
var losses = 0
var labels = ['wins', ' losses']
//Whithout seTimeout the chart is not updated
setTimeout(() => {
props.trades.forEach((trade) => {
if (trade.cprice) {
if (trade.cprice >= trade.price) {
wins++
} else {
losses++
}
}
})
newData.datasets[0].data = [wins, losses]
newData.labels = labels
setData(newData)
}, 1000)
}, [props.trades])
return (
<Doughnut
data={data}
options={config2}
redraw
/>
)
}
As you can see the child listens with useEffect to props changes, and then I process the props as I want to plot the necessary information on the Chart.
The thing is that in the beginning, the code didn't work (the Chart didn't display anything despite the props changed), I console logged the props, and it seems that something was happening too fast (if I console the length of the props.trades it showed me 0, but if I consoled the object it shows data in it) So that the forEach statement wasn't starting to iterate in the first place. When I added the setTimeout it started working if a put a 1000 milliseconds (with 500 milliseconds it doesn't work).
I'm a beginner at React and would be very interested in why this happens and what is the best approach to handle these small delays in memory that I quite don't understand.

react-hightchart: all values in event.point are null

I am using react-highchart-official in my project. I need to retrieve some values from the click event. In the component, the event listener is set using plotOptions like this:
plotOptions: {
series: {
point: {
events: {
click: event => {
this.props.onClick && this.props.onClick(event);
}
}
}
}
}
It gets invoked with event object which contains a point entry. point contains useful information regarding chart.
The chart component is used as:
import React from 'react';
import { render } from 'react-dom';
// Import Highcharts
import Highcharts from 'highcharts';
// Import our demo components
import Chart from './components/Chart.jsx';
// Load Highcharts modules
require('highcharts/modules/exporting')(Highcharts);
const chartOptions = {
title: {
text: ''
},
series: [
{
data: [[1, 'Highcharts'], [1, 'React'], [3, 'Highsoft']],
keys: ['y', 'name'],
type: 'pie'
}
]
};
class App extends React.Component {
state = { flag: true };
onChartClick(event) {
// All values of event.point are null. Not sure why.
// Even though it's not a synthetic event.
console.log(event.point);
this.setState({ flag: false });
}
render() {
const { flag } = this.state;
return (
<div>
<h1>Demos</h1>
<h2>Highcharts</h2>
{flag && (
<Chart
highcharts={Highcharts}
onClick={this.onChartClick.bind(this)}
/>
)}
</div>
);
}
}
For some unknown reasons, all the value inside point property of click event is set to null if I hide the chart. Is there any way I can avoid it? In the actual project on chart click I need to redirect user to somewhere. To imitate the situation, I have hidden the chart.
Codesandbox
This situation exactly shows what happened with your point data, see:
Demo: https://jsfiddle.net/BlackLabel/o70mLrnt/
var chart = Highcharts.chart('container', {
series: [{
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}]
});
console.log(chart.series[0].points[1])
chart.destroy();
Setting the flag to false unmounting the component which destroys the chart and later console.log doesn't have 'access' to chart and particular point properties.
If you need only a few data from the point a good option will be setting them in the state before the flag will be changed.
Like this - this will keep your point y value.
this.setState({
pointValue: event.point.y
});
Another solution which came to my mind is to set the whole point object to some variable, but here the setTimeout needs to be used.
Demo with setState solution and saving object to variable: https://codesandbox.io/s/highcharts-react-demo-dnbdv

How to stop drawing after completing one polygon or rectangle in DrawingManager on react-google-maps?

I'll use my code as a reference:
export default class DrawingContainer extends Component {
static propTypes = {
onPolygonComplete: PropTypes.func
};
state = {
drawingMode: 'rectangle'
};
render() {
return (
<DrawingManager
drawingMode={this.state.drawingMode}
onPolygonComplete={polygon => {
this.setState({
drawingMode: ''
}, () => {
if (this.props.onPolygonComplete) {
this.props.onPolygonComplete(convertPolygonToPoints(polygon));
}
});
}}
onRectangleComplete={rectangle => {
this.setState({
drawingMode: ''
}, () => {
if (this.props.onPolygonComplete) {
this.props.onPolygonComplete(
convertBoundsToPoints(rectangle.getBounds())
);
}
});
}}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
position: window.google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
window.google.maps.drawing.OverlayType.POLYGON,
window.google.maps.drawing.OverlayType.RECTANGLE
]
},
rectangleOptions: polygonOptions,
polygonOptions
}}
/>
);
}
}
So there are two approaches I followed to try to toggle the drawing mode to default drag mode after first drawing.
Either I save the current drawing mode(polygon or rectangle) to my own state and pass it to DrawingManager. I set my default varialbe in state called drawingMode to 'rectangle', pass it to the DrawingManager and then, in the function onRectangleComplete, I set it as an empty string, and it works since the map initially loads with the rectangle mode. But once I click on one of the drawing control, it never stops drawing, even though the variable is being set to an empty string. So I think there's a breach of controlled component here.
The second approach I tried was to explicitly try and find the google DrawingManager class to use it's setDrawingMode function. But I tried using ref on drawing manager and then went to it's state, and was able to see it there, but then I read the variable name DO_NOT_USE_THIS_ELSE_YOU_WILL_BE_FIRED - I believe the library prevents this approach.
So how do I use the drawing controls along with changing the drawing mode back to the default after I complete my first drawing?
handlePolygonComplete(polygon) {
console.log(this);
const paths = polygon.getPath().getArray();
if (paths.length < 3) {
polygon.setPaths([]);
alert("You need to enter at least 3 points.")
} else {
const coords = paths.map((a) => [a.lat(), a.lng()]);
this.setDrawingMode(null);
this.setOptions({ drawingControlOptions: { drawingModes: [] } });
window.addPolygonToState(coords);
}
and
<DrawingManager
onPolygonComplete={this.handlePolygonComplete}
>
Here I check if the user put at least 3 points, if he/she did, get its coordinates, and remove the drawing mode.
So I just set a toggle with a function that stopped rendering the DrawingManager
<GoogleMap
defaultZoom={10}
defaultCenter={new google.maps.LatLng(38.9072, -77.0369)}
>
{this.props.creatingPolygon && <DrawingManager
defaultDrawingMode={google.maps.drawing.OverlayType.POLYGON}
defaultOptions={
{
drawingControl: this.props.creatingPolygon,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
this.props.creatingPolygon && google.maps.drawing.OverlayType.POLYGON
],
}
}
}
onPolygonComplete={(polygon) => this.createDeliveryZone(polygon)}
/>}
</GoogleMap>

Resources