I have a problem with displays icons on google map.
Here is my code:
import React, { Component } from 'react'
import { compose, withProps, withStateHandlers } from 'recompose'
import { withScriptjs, withGoogleMap, GoogleMap, Marker, InfoWindow } from 'react-google-maps'
import MapStyles from './data/MapStyles'
export const Map = compose(
withStateHandlers(() => ({
isOpen: false,
}), {
onToggleOpen: ({ isOpen }) => () => ({
isOpen: !isOpen,
})
}),
withScriptjs,
withGoogleMap
)(props => {
return (
<GoogleMap
defaultZoom={13}
defaultCenter={{ lat: 52.229676, lng: 21.012229 }}
defaultOptions={{ styles: MapStyles }}
mapTypeControl={false}
>{ props.markers.map(marker => {
console.log(marker.location);
<Marker
{...marker}
key={marker.place_id}
position={marker.location}
title={marker.title}
icon={{
url: 'icons/icon.png'
}}
onClick={props.onToggleOpen}
>
{props.isOpen &&
<InfoWindow onCloseClick={props.onToggleOpen}>
<div>Open</div>
</InfoWindow>}
</Marker>
})}
</GoogleMap>
);})
export default Map
Positions for markers are displayed in console by console.log, but they don't display on a map ... I don't know why .... Maybe some of you know, why is this happen ... Here is link to this project on Github: https://github.com/hajczek/Neighborhood---Warsaw-Cultural-Map
Thanks for any hints.
Your missing a return in the map projection -
>{ props.markers.map(marker => {
console.log(marker.location);
<Marker
add a return before <Marker
>{ props.markers.map(marker => {
console.log(marker.location);
return <Marker
Working sample on codesandbox
Related
I'd like to ask if I'm using the map from React Leaflet (https://react-leaflet.js.org/) but how do I add the Base Map Gallery button to the map? like this example Basemap Gallery button on the image that I marked with red arrow and do I need to change or delete any of my code?
Example view of BasemapGallery but map from React-Leaflet - ReactJS:
import { React, useState, useEffect } from 'react'
import {
LayersControl,
MapContainer,
TileLayer,
Marker,
Popup,
useMapEvents,
} from 'react-leaflet'
import List from '../Component/List'
import L from 'leaflet'
import SearchControl from './SearchControl'
const { BaseLayer } = LayersControl
function LocationMarker() {
const [position, setPosition] = useState(null)
const map = useMapEvents({
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
})
return position === null ? null : (
<Marker position={position}>
<Popup>Location Me</Popup>
</Marker>
)
}
function MyLocationMe() {
const [map, setMap] = useState(null)
const [position, setPosition] = useState(null)
useEffect(() => {
if (!map) return
L.easyButton('fa-map-marker', () => {
map.locate().on('locationfound', function (e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
})
}).addTo(map)
}, [map])
return (
<div className="flex ml-auto">
<List />
<div className="w-4/5">
<MapContainer
center={{ lat: 51.505, lng: -0.09 }}
zoom={20}
style={{ height: '100vh' }}
whenCreated={setMap}
>
<SearchControl className="MarkerIcon" position="topright" />
<LayersControl position="topleft">
<BaseLayer checked name="OpenStreetMap">
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
/>
</BaseLayer>
</LayersControl>
<LocationMarker />
</MapContainer>
</div>
</div>
)
}
export default MyLocationMe
Example view of BasemapGallery but map from React-Leaflet - ReactJS:
Images
I have played around with the geolocation of javascript. So I created a react component, which shows your current location. I want to visualize this with Google Maps. It works fine so far, but however, if the current position moves outside the start map, the map does not pan. My goal is that the marker is always centered, and the map scrolls.
This is what I have so far. The current position is being passed to the component via the props props.latitude and props.longitude.
UPDATE
Now I know why this is not working.
window.google.maps.Map(document.getElementsByClassName("google-map"))
is not working. It does not find the map this way. So it cannot update its properties.
Anybody an idea how to access the current map?
Here is the code:
import React, {useState,useRef,useCallback} from 'react';
import { compose, withProps } from "recompose"
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps"
function Map(props) {
const [center, setCenter] = useState({ lat: props.latitude, lng: props.longitude });
const refMap = useRef(null);
const handlePositionChanged = () => {
let position = new window.google.maps.LatLng(parseInt(props.latitude), parseInt(props.longitude));
window.google.maps.Marker(document.getElementsByClassName("google-map-marker")).setPosition(position);
window.google.maps.Map(document.getElementsByClassName("google-map")).setCenter(position);
};
return (
<GoogleMap
className="google-map"
ref={refMap}
defaultZoom={19}
mapTypeId='satellite'
defaultCenter={{ lat: props.latitude, lng: props.longitude }}
onBoundsChanged={useCallback(handlePositionChanged)}
>
<Marker className="google-map-marker" position={{ lat: props.latitude, lng: props.longitude }} position_changed={useCallback(handlePositionChanged)} />
</GoogleMap>
);
}
export default compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIz&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `500px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap
)((props) => <Map latitude={props.latitude} longitude={props.longitude} />);
Instead of setting the center of the map and the marker using window.google.maps., you can use state values to change the <GoogleMap/> center parameter and the <Marker/> position parameter. So every time there's a change in the coordinates from geolocation, you need to change the state value of the Map's center and Marker's position and it the changes will then be reflected to the map. Here's a sample code snippet:
import React, { Component } from 'react';
import { withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
class Map extends Component {
constructor(props) {
super(props);
this.state = {
userPosition: { lat: 40.756795, lng: -73.954298 }
};
}
onMapLoad = () => {
navigator.geolocation.getCurrentPosition(position => {
const { latitude, longitude } = position.coords;
this.setState({
userPosition: { lat: latitude, lng: longitude }
});
});
};
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
center={this.state.userPosition}
defaultZoom={13}
onLoad={this.onMapLoad()}
>
<Marker position={this.state.userPosition} />
</GoogleMap>
));
return (
<div>
<GoogleMapExample
containerElement={<div style={{ height: `500px`, width: '500px' }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;
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>
);
}
}
I'm really new in ReactJS. I want to visualize a map of Bulgaria and set markers in each city only when I receive rainfall data. For now I try with examples from this link: React google-maps
But I get an error when placing the code in my file:
106:86-93 "export 'default' (imported as 'RainMap') was not found in './components/RainMap/RainMap'
Probably the error is very small but I do not know how to fix it.
My code:
import React, { Component } from 'react';
import 'react-select/dist/react-select.css';
const google = window.google;
const fetch = require("isomorphic-fetch");
const { compose, withProps, withHandlers } = require("recompose");
const {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
} = require("react-google-maps");
const { MarkerClusterer } = require("react-google-maps/lib/components/addons/MarkerClusterer");
const MapWithAMarkerClusterer = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withHandlers({
onMarkerClustererClick: () => (markerClusterer) => {
const clickedMarkers = markerClusterer.getMarkers()
console.log(`Current clicked markers length: ${clickedMarkers.length}`)
console.log(clickedMarkers)
},
}),
withScriptjs,
withGoogleMap
)(props =>
<GoogleMap
defaultZoom={3}
defaultCenter={{ lat: 25.0391667, lng: 121.525 }}
>
<MarkerClusterer
onClick={props.onMarkerClustererClick}
averageCenter
enableRetinaIcons
gridSize={60}
>
{props.markers.map(marker => (
<Marker
key={marker.photo_id}
position={{ lat: marker.latitude, lng: marker.longitude }}
/>
))}
</MarkerClusterer>
</GoogleMap>
);
class DemoApp extends React.PureComponent {
componentWillMount() {
this.setState({ markers: [] })
}
componentDidMount() {
const url = [
// Length issue
`https://gist.githubusercontent.com`,
`/farrrr/dfda7dd7fccfec5474d3`,
`/raw/758852bbc1979f6c4522ab4e92d1c92cba8fb0dc/data.json`
].join("")
fetch(url)
.then(res => res.json())
.then(data => {
this.setState({ markers: data.photos });
});
}
render() {
return (
<MapWithAMarkerClusterer markers={this.state.markers} />
)
}
}
<DemoApp />
You didn't import your RainMap component. Where in your directory is it stored? It seems to be trying to import from components folder -> RainMap folder -> RainMap.js
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 />
)
}
}