passing as props here
<MyMapComponent
isMarkerShown
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% }} />}
lat={lat}
lang={long}
/>
Map component
import React from 'react'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps"
const MyMapComponent = withScriptjs(withGoogleMap((props) => {
return (
< GoogleMap
defaultZoom={5}
defaultCenter={{ lat: props.lat, lng: props.lang }}
>
{props.isMarkerShown && <Marker position={{ lat: props.;at, lng: props.lang }} />}
</GoogleMap >
)
}));
export default MyMapComponent;
Related
I have the below JS code
A map renders just fine and when clicking the 1st click on the map, it creates and pins a marker on the place it was clicked. The 2nd time I click, it creates a 2nd marker and pins to the position that was clicked. Great!
However, when clicking the 3rd time, it doesn't create another marker! It instead moves the 2nd marker to the position of the 3rd click! Why is it doing that? It's supposed to create a 3rd marker, but for some reason, it moves the 2nd marker to a new position which should not be the case.
The marker is inside the tags too <Marker key={i} position={latLng} so it should work properly...
It seems that {props.isMarkerShown && <Marker position={props.markerPosition} />} is not creating a new instance for the marker after the 2nd marker is created for some reason...
import React from 'react';
import { compose, withStateHandlers } from "recompose";
import { InfoWindow, withGoogleMap, withScriptjs, GoogleMap, Marker } from 'react-google-maps';
const Map = compose(
withStateHandlers(() => ({
isMarkerShown: false,
markerPosition: null
}), {
onMapClick: ({ isMarkerShown }) => (e) => ({
markerPosition: e.latLng,
isMarkerShown:true
})
}),
withScriptjs,
withGoogleMap
)
(props =>
<GoogleMap
defaultZoom={8}
defaultCenter={{ lat: -34.397, lng: 150.644 }}
onClick={props.onMapClick}
>
{props.isMarkerShown && <Marker position={props.markerPosition} />}
</GoogleMap>
)
export default class MapContainer extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div style={{ height: '100%' }}>
<Map
googleMapURL="https://maps.googleapis.com/maps/api/js?key=VALIDAPIKEY"
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
{clicks.map((latLng, i) => (
<Marker key={i} position={latLng} />
))}
</div>
)
}
}
https://developers.google.com/maps/documentation/javascript/react-map
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>
After fetching a json file from server keep getting following mistake
TypeError: Cannot read property 'map' of undefined
I understand that have problems with locationsData, which I'm fetching, but I assumed that it already has an array format due to the format of the parsed data (example, please, see below).
import React, { useState } from "react";
import {
withGoogleMap,
withScriptjs,
GoogleMap,
Marker,
InfoWindow,
} from "react-google-maps";
let locationsData;
fetch("http:///locations")
.then(function (u) {
return u.json();
})
.then(function (json) {
locationsData = json;
});
function Map() {
const [selectedLoc, setSelectedLoc] = useState(null);
return (
<div className="App">
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 49.55848, lng: 23.312481 }}
>
{locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
{selectedLoc && (
<InfoWindow
position={{
lat: selectedLoc.gps[0],
lng: selectedLoc.gps[1],
}}
onCloseClick={() => {
setSelectedLoc(null);
}}
>
<div>
<h2>{selectedLoc.name}</h2>
</div>
</InfoWindow>
)}
</GoogleMap>
</div>
);
}
const WrappedMap = withScriptjs(withGoogleMap(Map));
export default function App() {
return (
<div style={{ width: "100vw", height: "100vh" }}>
<WrappedMap
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=000`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
Server data example:
[
{
"gps": [11, 11],
"_id": "1",
"name": "Name1"
},
{
"gps": [22, 22],
"_id": "2",
"name": "Name2"
}
]
You will need to use useEffect and do the fetching in there. You will also have to store the data in the state so that the component will re-render once the data are fetched.
function Map() {
const [selectedLoc, setSelectedLoc] = useState(null);
const [locationsData, setLocationsData] = useState([]);
useEffect(() => {
fetch("http:///locations")
.then(function(u) {
return u.json();
})
.then(function(json) {
setLocationsData(json);
});
}, [])
return (
<div className="App">
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 49.55848, lng: 23.312481 }}
>
{locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
{selectedLoc && (
<InfoWindow
position={{
lat: selectedLoc.gps[0],
lng: selectedLoc.gps[1],
}}
onCloseClick={() => {
setSelectedLoc(null);
}}
>
<div>
<h2>{selectedLoc.name}</h2>
</div>
</InfoWindow>
)}
</GoogleMap>
</div>
);
}
before it gets assigned (locationsData = json;), the locationsData is undefined as you stated here in the initial declaration: let locationsData;
so undefined.map() will throw you the error, you can do this to remain a consistent behavior:
let locationsData = [];
or you can have a validation before calling the .map() function:
{Array.isArray(locationsData) && locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
As #Gabriele pointed out, the fetch operation is placed outside of the component. You can do this to ensure the results get assigned correctly and the component will render it:
function Map() {
const [selectedLoc, setSelectedLoc] = useState(null);
const [locationsData, setLocationsData] = useState([]);
useEffect(() => {
fetch("http:///locations")
.then(u => u.json())
.then(json => setLocationsData(json));
}, []); // Empty dependency, acts similar to componentDidMount
return (
<div className="App">
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 49.55848, lng: 23.312481 }}
>
{locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
{selectedLoc && (
<InfoWindow
position={{
lat: selectedLoc.gps[0],
lng: selectedLoc.gps[1],
}}
onCloseClick={() => {
setSelectedLoc(null);
}}
>
<div>
<h2>{selectedLoc.name}</h2>
</div>
</InfoWindow>
)}
</GoogleMap>
</div>
);
}
Initialize locationData with empty array..
let locationsData= [];
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
I took the react-google-maps MapWithAMarker example :
import React from 'react';
import { compose, withProps, lifecycle} from 'recompose';
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
} from 'react-google-maps';
import keys from '../../components/config/keys';
const MapWithAMarker = compose(
withProps({
googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${keys.google_maps_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={8}
defaultCenter={{ lat: props.lat, lng: props.lng }}>
<Marker position={{ lat: props.lat, lng: props.lng }}/>
</GoogleMap>
);
export default MapWithAMarker;
and I use it like this:
<MapWithAMarker lat={parseFloat(excursion.lat)}
lng={parseFloat(excursion.lng)} />
I use React router in my application.
Observed behaviour :
When i render the page for the first time, the map renders correctly.
If i click on a link to rerender the page with a different marker position, the map fails to load and just renders a empty grey rectangle with only "press ctrl plus scroll to zoom" when i scroll on it.
Solved :
I needed to change the defaultCenter to center and defaultZoom to zoom :
<GoogleMap zoom={8}
center={{ lat: props.lat, lng: props.lng }}>
<Marker position={{ lat: props.lat, lng: props.lng }}/>
</GoogleMap>