I have the google-maps-react in my project, but I don't know how to get all markers from the map?
import React, { Component } from "react";
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";
import "../Body/Map.css";
import marker_icon from "../../img/marker_icon.png";
import hover_icon from "../../img/hover_icon.png";
import { Grid, Row, Col } from "react-bootstrap";
/*global google*/
export class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {}
};
}
onMarkerClick = (props, marker, e) => {
this.setState({
selectedPlace: props,
activeMarker: marker,
showingInfoWindow: true
});
};
onMapClicked = props => {
if (this.state.showingInfoWindow) {
this.setState({
showingInfoWindow: false,
activeMarker: null
});
}
};
addMarker = (mapProps, map) => {
var marker = new google.maps.Marker({
position: {},
map: map
});
};
render() {
const google = window.google;
const data = this.props.data;
return (
<div className="map-container">
<Map
google={this.props.google}
className={"map"}
zoom={1}
onClick={this.onMapClicked}
onReady={this.addMarker}
>
{data.map(item => (
<Marker
key={item.id}
title={item.name}
name={item.name}
position={{ lat: item.lat, lng: item.lng }}
onClick={this.onMarkerClick}
/>
))}
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
>
<div className="info">
<h1>{this.state.selectedPlace.name}</h1>
</div>
</InfoWindow>
</Map>
</div>
);
}
}
export default GoogleApiWrapper({
apiKey: "AIzaSyDLgdweTnvhPnUE5yzdxcMeK876cFtMaSk"
})(MapContainer);
I had a similar issue. I wanted to remove all old markers and add a list of new markers. This is my code to fix it:
const MyMap = (props) => {
const [markers, setMarkers] = React.useState([])
React.useEffect(() => {
var markerArr = []
points.map(p => {
markerArr.push(<Marker position={{lat: p.lat, lng: p.lng}} />)
}
)
setMarkers(markerArr)
}, [])
const MarkerUpdater = (day) => {
var markerArr = []
points.map(p => {
markerArr.push(
<Marker position={{lat: p.lat, lng: p.lng}} />
)
}
)
setMarkers(markerArr)
}
return <Map> {markers} </Map>
}
NOTE
you should call MarkerUpdater everywhere you want to update markers
You probably meant to access google.maps.Marker objects, if so, you could consider the utilize Callback Refs:
1) assign ref attribute to store a reference to a Marker node:
<Marker ref={this.onMarkerMounted}
key={item.id}
title={item.name}
name={item.name}
position={{ lat: item.lat, lng: item.lng }}
/>
2) save marker instance into markerObjects array:
export class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
markerObjects: []
};
this.onMarkerMounted = element => {
this.setState(prevState => ({
markerObjects: [...prevState.markerObjects, element.marker]
}))
};
}
render() {
const google = window.google;
const data = this.props.data;
return (
<div className="map-container">
<Map
google={this.props.google}
className={"map"}
zoom={4}
defaultCenter={{ lat: -35.0317893, lng: 125.219989 }}
position={{ lat: -35.0317893, lng: 125.219989 }}
>
{data.map(item => (
<Marker ref={this.onMarkerMounted}
key={item.id}
title={item.name}
name={item.name}
position={{ lat: item.lat, lng: item.lng }}
/>
))}
</Map>
</div>
);
}
}
Related
I was tried to get the onClick event on the marker but I'm not able to get that. I was going through the document(google-maps-react) also I have created the static position and add marker but still, it's not getting it. can someone help me?
I want to get the onClick event working on marker. I have tried so much but I'm not able to find the solution. the document also mentions that properly named so I was given the exact name that they provided in the document.
NPM Package: https://www.npmjs.com/package/google-maps-react
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";
import React, { Component } from "react";
class WithMarkers extends Component {
state = {
activeMarker: {},
selectedPlace: {},
showingInfoWindow: false
};
onMarkerClick = (props, marker) =>
this.setState(
{
activeMarker: marker,
selectedPlace: props,
showingInfoWindow: true
},
() => {
console.log("Click on marker");
}
);
onInfoWindowClose = () =>
this.setState({
activeMarker: null,
showingInfoWindow: false
});
onMapClicked = () => {
if (this.state.showingInfoWindow)
this.setState({
activeMarker: null,
showingInfoWindow: false
});
};
render() {
if (!this.props.loaded) return <div>Loading...</div>;
return (
<Map
className="map"
google={this.props.google}
onClick={this.onMapClicked}
style={{ height: "100%", position: "relative", width: "100%" }}
zoom={14}
>
<Marker
name="SOMA"
onClick={this.onMarkerClick}
position={{ lat: 37.778519, lng: -122.40564 }}
/>
<Marker
name="Dolores park"
onClick={this.onMarkerClick}
position={{ lat: 37.759703, lng: -122.428093 }}
/>
<Marker name="Current location" onClick={this.onMarkerClick} />
<InfoWindow
marker={this.state.activeMarker}
onClose={this.onInfoWindowClose}
visible={this.state.showingInfoWindow}
>
<div>
<h1>{this.state.selectedPlace.name}</h1>
</div>
</InfoWindow>
<InfoWindow position={{ lat: 37.765703, lng: -122.42564 }} visible>
<small>
Click on any of the markers to display an additional info.
</small>
</InfoWindow>
</Map>
);
}
}
// export default WithMarkers;
export default GoogleApiWrapper({
apiKey: "KEY"
})(WithMarkers);
I am using an application that displays a Google map with react Google Maps have multiple pins installed, and the state changes by scrolling, and the active flight changes according to the state.
At that time, the center of the Google map is set to be an activity, but the Google map is re-rendered when the state changes. I don't know how to prevent rendering.
 Google Maps has NPM library. It uses react-google-maps and is implemented using hooks. I tried to return false with useEffect (), but I didn't hear it as it is. Please tell me
MapComponent(HOC)
import React from "react";
import { withGoogleMap, GoogleMap, withScriptjs, Marker, InfoWindow } from "react-google-maps";
import { compose, withProps, withHandlers, withStateHandlers } from "recompose";
const MapWithPlaces = compose(
withProps({
googleMapURL:
`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_PLACE_API_KEY}&libraries=geometry,drawing,places`,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: "400px", width: "100%" }} />,
mapElement: <div style={{ height: "100%" }} />
}),
withStateHandlers(
props => ({
infoWindows: props.places.map(p => {
return { isOpen: false };
}),
defaultCenter: { 'lat': props.lat, 'lng': props.lng }
}),
{
onToggleOpen: ({ infoWindows }) => selectedIndex => ({
infoWindows: infoWindows.map((iw, i) => {
iw.isOpen = selectedIndex === i;
return iw;
})
})
}
),
withHandlers(() => {
const refs = {
map: undefined,
}
console.log(refs);
return {
onMapMounted: () => ref => {
refs.map = ref
},
onZoomChanged: ({ onZoomChange }) => (props) => {
const center = { 'lat': parseFloat(props.lat, 10), 'lng': parseFloat(props.lng, 10) }
refs.map.pantTo(center)
}
}
}),
withScriptjs,
withGoogleMap
)(props => (
<GoogleMap defaultZoom={props.zoom} defaultCenter={props.center} key={props.key} ref={map}>
{props.places &&
props.places.map((place, i) => {
let lat = parseFloat(place.lat, 10);
let lng = parseFloat(place.lng, 10);
return (
<Marker
id={place.id}
key={place.key}
position={{ lat: lat, lng: lng }}
title={place.name}
onClick={props.onToggleOpen.bind(this, i)}
opacity={place.key === props.step ? 1 : 0.5}
label={place.day === props.currentDay ? place.dayIndex.toString() : ''}
>
{props.infoWindows[i].isOpen && (
<InfoWindow onCloseClick={props.onToggleOpen.bind(i)}>
<div>{place.name}</div>
</InfoWindow>
)}
</Marker>
);
})}
</GoogleMap>
));
export default MapWithPlaces;
MapComponent(hooks)
import React, { useState, useEffect, useRef } from "react";
import { withGoogleMap, withScriptjs, GoogleMap, Marker, InfoWindow } from "react-google-maps";
// import mapStyles from "./mapStyles";
const MapCreate = React.memo((props) => {
// const [selectedPark, setSelectedPark] = useState(null);
const mapRef = useRef()
useEffect(() => {
console.log("props updates")
console.log(props);
const mapCenter = {
lat: parseFloat(props.places[props.step].lat, 10),
lng: parseFloat(props.places[props.step].lng, 10)
}
return false
// refMap.current.panTo(mapCenter) //move the map to new location
}, [props]);
return (
<GoogleMap defaultZoom={14} center={{ lat: props.center.lat, lng: props.center.lng }} ref={mapRef}>
{props.places && props.places.map((place, i) => {
let lat = parseFloat(place.lat, 10);
let lng = parseFloat(place.lng, 10);
return (
<Marker
id={place.id}
key={place.key}
position={{ lat: lat, lng: lng }}
title={place.name}
opacity={place.key === props.step ? 1 : 0.5}
label={place.day === props.currentDay ? place.dayIndex.toString() : ''}
>
</Marker>
)
})}
</GoogleMap>
)
})
const MapWrapped = withScriptjs(withGoogleMap(MapCreate));
export default function Map(props) {
const mapRef = useRef(null)
return (
<div style={{ width: "100%", height: "400px" }}>
<MapWrapped
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${process.env.REACT_APP_GOOGLE_PLACE_API_KEY}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: "400px", width: "100%" }} />}
mapElement={<div style={{ height: `100%` }} />}
{...props}
/>
</div>
);
}
Try #shouldcomponentupdate
shouldComponentUpdate(nextProps, nextState)
Use shouldComponentUpdate() to let React know if a component’s output
is not affected by the current change in state or props. The default
behavior is to re-render on every state change, and in the vast
majority of cases you should rely on the default behavior.
shouldComponentUpdate() is invoked before rendering when new props or
state are being received. Defaults to true. This method is not called
for the initial render or when forceUpdate() is used
How to update ReactGoogleMap after receiving data from the server?
This is how I create Google Map using react-google-maps API.
import React from "react"
import { compose, withProps } from "recompose"
import { withScriptjs, withGoogleMap, GoogleMap, Marker , Polyline} from "react-google-maps"
import TextField from "#material-ui/core/TextField";
import Button from "components/CustomButtons/Button.jsx";
import './Maps.css';
import axios from "axios";
const pathCoordinates = [
{ lat: 1.322459, lng: 103.853972 },
{ lat: 1.39227, lng: 103.752 }
];
const MyMapComponent = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&v=3.exp&libraries=geometry,drawing",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `80vh` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap
)((props) =>
<GoogleMap
defaultZoom={12}
defaultCenter={{ lat: 1.322459, lng: 103.853972 }}
>
<div id='map_controls' class='toolbox'>
<TextField
id="date"
label="Date"
type="date"
defaultValue= ""
InputLabelProps={{
shrink: true,
style: { color: '#fff' }
}}
value={props.date}
onChange={props.handleChange('date')}
/>
<Button color="primary" onClick={props.handleSubmit}>Select Date</Button>
</div>
{console.log("drawing...............")}
{props.drawMap()}
</GoogleMap>
)
const initialState = {
date: "",
data: []
};
class Maps extends React.Component {
constructor(props) {
super(props);
this.state = initialState;
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.drawMap = this.drawMap.bind(this);
}
componentDidMount() {
console.log(" componentDidMount "+this.state.date);
}
handleChange = name => event => {
this.setState({ [name]: event.target.value });
};
handleSubmit(event) {
const input = {};
input["date"] = this.state.date;
axios.post("localhost:4000/readMap", input)
.then(response => {
console.log({response});
this.setState({data: response.data});
})
.catch(error => {console.log(error.response)});
event.preventDefault();
}
drawMap(){
if(!(this.state.date==="")){
var rows = [];
for (var i = 0; i < 2; i++) {
if(i===0){
rows.push(<Marker label= {(i+1).toString()} position={{ lat: 1.39227, lng: 103.752 }} key={i} />);
}else if(i===1){
rows.push(<Marker label= {(i+1).toString()} position={{ lat: 1.322459, lng: 103.853972 }} key={i} />);
}else{
}
}
return (<div>{rows}<Polyline
path={pathCoordinates}
geodesic={true}
options={{
strokeColor: "#ff2527",
strokeOpacity: 0.75,
strokeWeight: 2
}}
/></div>);
}else{
console.log("no date");
}
}
render() {
this.drawMap();
return (
<MyMapComponent
handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
drawMap={this.drawMap}
/>
)
}
}
export default Maps;
I want to draw the marker after I receive data from the database. I successfully read the input(which is a date) from the user and send this data to a server to get the data of this date from the database. Data is successfully received and able to print it in the console. However, I have no idea how to update MyMapComponent to display the marker of this date. I run drawMap() function again after I get the data but the MyMapComponent is not updated after I run drawMap().
I found the solution.
render() {
console.log("render::::::::::::::::::::");
return (
<MyMapComponent
handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
drawMap={this.drawMap}
>
{this.drawMap()}
</MyMapComponent>
)
}
I found a lot of useful information on google maps documentation but with simple use of js in html, in case of react honestly I don't understand it.
Source code:
import React, { Component } from 'react';
import {Map, InfoWindow, Marker, GoogleApiWrapper} from 'google-maps-react';
export class MainMap extends Component {
render() {
return (
<div>
<h1 className="text-center">My Maps</h1>
<Map google={this.props.google}
style={{width: '80%', margin: 'auto'}}
className={'map'}
zoom={14}>
<Marker
title={'The marker`s title will appear as a tooltip.'}
name={'SOMA'}
position={{lat: 37.778519, lng: -122.405640}} />
<Marker
name={'Dolores park'}
position={{lat: 37.759703, lng: -122.428093}} />
<Marker />
<Marker
name={'Your position'}
position={{lat: 46.475640, lng: 30.759497}}/>
</Map>
</div>
);
}
}
export default GoogleApiWrapper({
apiKey: (MY-API-KEY)
})(MainMap);
i want to add marker by clicking on map and don't know how...
help please!
The map has an onClick prop which you can give a function to handle clicks on the map. The third argument to this function includes the coordinates of the click.
You could use these coordinates to add a marker to your state that you use in the render method.
Example
class MainMap extends Component {
constructor(props) {
super(props);
this.state = {
markers: [
{
title: "The marker`s title will appear as a tooltip.",
name: "SOMA",
position: { lat: 37.778519, lng: -122.40564 }
}
]
};
this.onClick = this.onClick.bind(this);
}
onClick(t, map, coord) {
const { latLng } = coord;
const lat = latLng.lat();
const lng = latLng.lng();
this.setState(previousState => {
return {
markers: [
...previousState.markers,
{
title: "",
name: "",
position: { lat, lng }
}
]
};
});
}
render() {
return (
<div>
<h1 className="text-center">My Maps</h1>
<Map
google={this.props.google}
style={{ width: "80%", margin: "auto" }}
className={"map"}
zoom={14}
onClick={this.onClick}
>
{this.state.markers.map((marker, index) => (
<Marker
key={index}
title={marker.title}
name={marker.name}
position={marker.position}
/>
))}
</Map>
</div>
);
}
}
const App = GoogleApiWrapper({
apiKey: (MY-API-KEY)
})(MainMap);
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 />
)
}
}