Passing Data Using Props to Display Polylines with Google Maps - javascript

Here is the reactjs code for displaying the movement of a vehicle on google map.
In the code, for the path array, latitude and longitude coordinates are assigned as hard-code values.
What I need is, how should pass latitude and longitude coordinates to "path" array from another component using props.
import React from "react";
import {
withGoogleMap,
withScriptjs,
GoogleMap,
Polyline,
Marker,
} from "react-google-maps";
class Map extends React.Component {
state = {
progress: [],
};
path = [
{ lat: 18.558908, lng: -68.389916 },
{ lat: 18.558853, lng: -68.389922 },
{ lat: 18.558375, lng: -68.389729 },
{ lat: 18.558032, lng: -68.389182 },
{ lat: 18.55805, lng: -68.388613 },
{ lat: 18.558256, lng: -68.388213 },
{ lat: 18.558744, lng: -68.387929 },
];
velocity = 5;
initialDate = new Date();
getDistance = () => {
// seconds between when the component loaded and now
const differentInTime = (new Date() - this.initialDate) / 1000; // pass to seconds
return differentInTime * this.velocity; // d = v*t -- thanks Newton!
};
componentDidMount = () => {
this.interval = window.setInterval(this.moveObject, 1000);
};
componentWillUnmount = () => {
window.clearInterval(this.interval);
};
moveObject = () => {
const distance = this.getDistance();
if (!distance) {
return;
}
let progress = this.path.filter(
(coordinates) => coordinates.distance < distance
);
const nextLine = this.path.find(
(coordinates) => coordinates.distance > distance
);
if (!nextLine) {
this.setState({ progress });
return; // it's the end!
}
const lastLine = progress[progress.length - 1];
const lastLineLatLng = new window.google.maps.LatLng(
lastLine.lat,
lastLine.lng
);
const nextLineLatLng = new window.google.maps.LatLng(
nextLine.lat,
nextLine.lng
);
// distance of this line
const totalDistance = nextLine.distance - lastLine.distance;
const percentage = (distance - lastLine.distance) / totalDistance;
const position = window.google.maps.geometry.spherical.interpolate(
lastLineLatLng,
nextLineLatLng,
percentage
);
progress = progress.concat(position);
this.setState({ progress });
};
componentWillMount = () => {
this.path = this.path.map((coordinates, i, array) => {
if (i === 0) {
return { ...coordinates, distance: 0 }; // it begins here!
}
const { lat: lat1, lng: lng1 } = coordinates;
const latLong1 = new window.google.maps.LatLng(lat1, lng1);
const { lat: lat2, lng: lng2 } = array[0];
const latLong2 = new window.google.maps.LatLng(lat2, lng2);
// in meters:
const distance = window.google.maps.geometry.spherical.computeDistanceBetween(
latLong1,
latLong2
);
return { ...coordinates, distance };
});
console.log(this.path);
};
render = () => {
return (
<GoogleMap
defaultZoom={16}
defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
>
{this.state.progress && (
<>
<Polyline
path={this.state.progress}
options={{ strokeColor: "#FF0000 " }}
/>
<Marker
position={this.state.progress[this.state.progress.length - 1]}
/>
</>
)}
</GoogleMap>
);
};
}
const MapComponent = withScriptjs(withGoogleMap(Map));
export default () => (
<MapComponent
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`, width: "940px" }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
);
Here is sample data from json object, which I get from other component.I need to pass this data using props to the above path array.
[]
0: {lat: 6.8667528, lng: 79.8769134}
1: {lat: 6.8667112, lng: 79.8769667}
2: {lat: 6.8666556, lng: 79.8769856}
3: {lat: 6.8666023, lng: 79.8769823}
4: {lat: 6.8665584, lng: 79.8770412}
5: {lat: 6.8665478, lng: 79.8771573}
6: {lat: 6.8665295, lng: 79.8772695}
7: {lat: 6.8664823, lng: 79.8774434}
8: {lat: 6.8664434, lng: 79.8777684}
9: {lat: 6.8664023, lng: 79.87823}
10: {lat: 6.8663373, lng: 79.8786712}
11: {lat: 6.86628, lng: 79.87902}
12: {lat: 6.8662312, lng: 79.879335}
13: {lat: 6.8662145, lng: 79.8795562}
14: {lat: 6.8662095, lng: 79.879695}
15: {lat: 6.8661978, lng: 79.8797523}
16: {lat: 6.8659873, lng: 79.8798639}
Can anyone help me to build this? Thanks for your help!

This is a sample code Note: use your own API key for the code to work) and a code snippet below on how I implement it. In the index.js, I put the path array in json file then imported the json file to be used as an element in my map. Then in my Map.js, I set the constuctor(props) and super(props). I put the react-google-maps <GoogleMap> in the render inside the GoogleMapExample variable. Then I use this variable in the return. In the componentWillMount function of your code, you need to use this.props.path.map to get the value of your path from the props.
Index.js
import React, { Component } from "react";
import { render } from "react-dom";
import { withScriptjs } from "react-google-maps";
import Map from "./Map";
import "./style.css";
import jsonPath from "./data.json";
const App = () => {
const MapLoader = withScriptjs(Map);
return (
<MapLoader
path={jsonPath}
googleMapURL="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry,places"
loadingElement={<div style={{ height: `100%` }} />}
/>
);
};
render(<App />, document.getElementById("root"));
Map.js
import React, { Component } from "react";
import {
withGoogleMap,
GoogleMap,
Polyline,
Marker
} from "react-google-maps";
class Map extends Component {
constructor(props) {
super(props);
this.state = {
progress: []
};
}
velocity = 5;
initialDate = new Date();
getDistance = () => {
// seconds between when the component loaded and now
const differentInTime = (new Date() - this.initialDate) / 1000; // pass to seconds
return differentInTime * this.velocity; // d = v*t -- thanks Newton!
};
componentDidMount = () => {
this.interval = window.setInterval(this.moveObject, 1000);
console.log(this.props.path);
};
componentWillUnmount = () => {
window.clearInterval(this.interval);
};
moveObject = () => {
const distance = this.getDistance();
if (!distance) {
return;
}
let progress = this.path.filter(
coordinates => coordinates.distance < distance
);
const nextLine = this.path.find(
coordinates => coordinates.distance > distance
);
if (!nextLine) {
this.setState({ progress });
return; // it's the end!
}
const lastLine = progress[progress.length - 1];
const lastLineLatLng = new window.google.maps.LatLng(
lastLine.lat,
lastLine.lng
);
const nextLineLatLng = new window.google.maps.LatLng(
nextLine.lat,
nextLine.lng
);
// distance of this line
const totalDistance = nextLine.distance - lastLine.distance;
const percentage = (distance - lastLine.distance) / totalDistance;
const position = window.google.maps.geometry.spherical.interpolate(
lastLineLatLng,
nextLineLatLng,
percentage
);
progress = progress.concat(position);
this.setState({ progress });
};
componentWillMount = () => {
this.path = this.props.path.map((coordinates, i, array) => {
if (i === 0) {
return { ...coordinates, distance: 0 }; // it begins here!
}
const { lat: lat1, lng: lng1 } = coordinates;
const latLong1 = new window.google.maps.LatLng(lat1, lng1);
const { lat: lat2, lng: lng2 } = array[0];
const latLong2 = new window.google.maps.LatLng(lat2, lng2);
// in meters:
const distance = window.google.maps.geometry.spherical.computeDistanceBetween(
latLong1,
latLong2
);
return { ...coordinates, distance };
});
console.log(this.path);
};
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
defaultZoom={16}
defaultCenter={{ lat: 6.8667528, lng: 79.8769134 }}
>
{this.state.progress && (
<>
<Polyline
path={this.state.progress}
options={{ strokeColor: "#FF0000 " }}
/>
<Marker
position={this.state.progress[this.state.progress.length - 1]}
/>
</>
)}
</GoogleMap>
));
return (
<div>
<GoogleMapExample
containerElement={<div style={{ height: `500px`, width: "500px" }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;

Related

#react-google-maps/api flickering issue with react 18

I'm using Next.js version 12.3.1 and React.js 18.2.0. When I select point A and point B the direction service and direction renderer gets called and the map prints the direction with the markers. But when I change points A and B the map prints a new direction but the very first direction/line stays on the map.
How do I fix the issue?
Here is the Map functions file:
import React, { useCallback, useState } from "react";
import CustomGoogleMap from "#components/core/CustomGoogleMap";
import { Box } from "#mui/material";
import { anyObjectType } from "#services/types";
import MapAPI from "#services/api/map";
import { CreateBookingActions } from "#services/constants";
import { useCreateBookingContext } from "#contexts/CreateBookingContext";
const BookingMap: React.FC<BookingMapProps> = ({
memoizedloadingPoint,
memoizedunloadingPoint,
memoizedwaypointsList,
setToast,
setLoadingPoint,
setUnLoadingPoint,
}) => {
const cbCtx = useCreateBookingContext();
const { state, dispatch } = cbCtx;
const { waypointsList } = state;
const [call, setCall] = useState(false);
const handleLoadingPointDragLocation = useCallback(
async (lat: number, lng: number) => {
if (lat && lng) {
const query = {
latlng: `${lat},${lng}`,
};
const { response, error }: any = await MapAPI.onDrag(query);
if (response) {
setLoadingPoint({
...response.data.data,
});
} else {
setToast("Somthing went wrong", "error");
}
}
},
[]
);
const handleUnLoadingPointDragLocation = useCallback(
async (lat: number, lng: number) => {
if (lat && lng) {
const query = {
latlng: `${lat},${lng}`,
};
const { response, error }: any = await MapAPI.onDrag(query);
if (response) {
setUnLoadingPoint({
...response.data.data,
});
} else {
setToast("Somthing went wrong", "error");
}
}
},
[]
);
const setWaypointsList = (val: any[]) => {
dispatch({
type: CreateBookingActions.SET_WAYPOINT_LIST,
payload: val,
});
};
const handleStopageDragLocation = useCallback(
async (lat: number, lng: number, index: number) => {
if (lat && lng) {
const query = {
latlng: `${lat},${lng}`,
};
const { response, error }: any = await MapAPI.onDrag(query);
if (response) {
const updatedWaypoints = JSON.parse(JSON.stringify(waypointsList));
updatedWaypoints.splice(index, 1, { ...response.data.data });
setWaypointsList([...updatedWaypoints]);
setCall(true);
} else {
setToast("Somthing went wrong", "error");
}
}
},
[]
);
return (
<Box sx={{ height: "420px" }}>
<CustomGoogleMap
call={call}
setCall={setCall}
loadingP={memoizedloadingPoint}
unloadingP={memoizedunloadingPoint}
waypointsList2={memoizedwaypointsList}
handleLoadingPointDragLocation={handleLoadingPointDragLocation}
handleUnLoadingPointDragLocation={handleUnLoadingPointDragLocation}
handleStopageDragLocation={handleStopageDragLocation}
/>
</Box>
);
};
export default BookingMap;
interface BookingMapProps {
memoizedloadingPoint: anyObjectType;
memoizedunloadingPoint: anyObjectType;
memoizedwaypointsList: any[];
setToast: (a: string, b: string) => void;
setLoadingPoint: (a: anyObjectType) => void;
setUnLoadingPoint: (a: anyObjectType) => void;
}
Here is the google map file:
import React, { useEffect, useState, memo } from "react";
import {
GoogleMap,
MarkerF,
DirectionsRenderer,
DirectionsService,
InfoWindow,
useLoadScript,
LoadScriptNext,
} from "#react-google-maps/api";
import LoadingMarker from "../SvgIcons/loading-marker.svg";
import UnLoadingMarker from "../SvgIcons/unloading-marker.svg";
import StoppageIcon from "../SvgIcons/stopageIcon.svg";
import { CircularProgress } from "#mui/material";
import { Box } from "#mui/system";
import { isEmptyArray } from "#services/utils";
import { anyObjectType, Dispatcher } from "#services/types";
const containerStyle = {
width: "100%",
height: "100%",
};
const center = {
lat: 23.810331,
lng: 90.412521,
};
interface CustomLatLong {
latitude: number;
longitude: number;
textEn: string;
}
type CustomDirectionsWaypoint = google.maps.DirectionsWaypoint & CustomLatLong;
interface CustomGoogleMapProps {
call: Boolean;
setCall: Dispatcher<boolean>;
handleStopageDragLocation?: (a: number, b: number, c: number) => void;
handleLoadingPointDragLocation?: (a: number, b: number) => void;
handleUnLoadingPointDragLocation?: (a: number, b: number) => void;
waypointsList2: CustomDirectionsWaypoint[];
loadingP: anyObjectType;
unloadingP: anyObjectType;
isAddressModal?: Boolean;
}
const CustomGoogleMap: React.FC<CustomGoogleMapProps> = (props) => {
const {
call,
setCall,
loadingP,
unloadingP,
waypointsList2,
handleLoadingPointDragLocation,
handleUnLoadingPointDragLocation,
handleStopageDragLocation,
isAddressModal = false,
} = props;
// const { isLoaded, loadError } = useLoadScript({
// googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!,
// });
const [infoBox, setInfoWindow] = useState({
position: {
lat: 0,
lng: 0,
},
info: "",
});
const [directions, setDirections] = useState(null);
console.log("point:", loadingP, unloadingP);
useEffect(() => {
if (loadingP.latitude && unloadingP.latitude) {
setCall(true);
}
}, [loadingP.latitude, unloadingP.latitude]);
const directionsCallback = (response: any) => {
if (response !== null) {
console.log("directionsCallback called");
if (response.status === "OK") {
setCall(false);
setDirections(response);
}
}
};
const getDirectionRender = () => {
return (
<DirectionsService
options={{
destination: {
lat: unloadingP.latitude,
lng: unloadingP.longitude,
},
origin: {
lat: loadingP.latitude,
lng: loadingP.longitude,
},
travelMode: google.maps.TravelMode.DRIVING,
waypoints: waypointsList2.map(({ latitude, longitude }) => {
return {
location: {
lat: latitude,
lng: longitude,
}.toString(),
stopover: false,
};
}),
}}
callback={directionsCallback}
/>
);
};
// if (loadError) {
// return <div>Map cannot be loaded right now, sorry.</div>;
// }
const renderMap = () => {
return (
<LoadScriptNext
googleMapsApiKey={process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!}
>
<GoogleMap
mapContainerStyle={containerStyle}
center={
loadingP.latitude
? {
lat: loadingP.latitude,
lng: loadingP.longitude,
}
: center
}
zoom={10}
onClick={({ latLng }) => {
isAddressModal &&
handleLoadingPointDragLocation &&
handleLoadingPointDragLocation(latLng!.lat(), latLng!.lng());
}}
>
{loadingP.latitude &&
unloadingP.latitude &&
call &&
getDirectionRender()}
{directions && (
<DirectionsRenderer
options={{
directions: directions,
suppressMarkers: true,
}}
/>
)}
{infoBox.position.lat && (
<InfoWindow
// options={infoBoxOptions}
position={infoBox.position}
onCloseClick={() =>
setInfoWindow({
position: {
lat: 0,
lng: 0,
},
info: "",
})
}
>
<p> {infoBox.info}</p>
</InfoWindow>
)}
<MarkerF
key={loadingP.latitude}
draggable
onDragEnd={({ latLng }) => {
handleLoadingPointDragLocation &&
handleLoadingPointDragLocation(latLng!.lat(), latLng!.lng());
}}
position={{ lat: loadingP.latitude, lng: loadingP.longitude }}
icon={LoadingMarker}
onClick={() =>
setInfoWindow({
...infoBox,
position: {
lat: loadingP.latitude,
lng: loadingP.longitude,
},
info: loadingP.textEn,
})
}
/>
<MarkerF
key={unloadingP.latitude}
draggable
onDragEnd={({ latLng }) => {
handleUnLoadingPointDragLocation &&
handleUnLoadingPointDragLocation(latLng!.lat(), latLng!.lng());
}}
position={{
lat: unloadingP.latitude,
lng: unloadingP.longitude,
}}
icon={UnLoadingMarker}
onClick={() =>
setInfoWindow({
...infoBox,
position: {
lat: unloadingP.latitude,
lng: unloadingP.longitude,
},
info: unloadingP.textEn,
})
}
/>
{!isEmptyArray(waypointsList2) &&
waypointsList2.map((item, index) => {
return (
<MarkerF
key={index}
draggable
visible
onDragEnd={({ latLng }) => {
handleStopageDragLocation &&
handleStopageDragLocation(
latLng!.lat(),
latLng!.lng(),
index
);
}}
position={{
lat: item.latitude,
lng: item.longitude,
}}
icon={StoppageIcon}
onClick={() =>
setInfoWindow({
...infoBox,
position: {
lat: item.latitude,
lng: item.longitude,
},
info: item.textEn,
})
}
/>
);
})}
</GoogleMap>
</LoadScriptNext>
);
};
return renderMap();
};
export default memo(CustomGoogleMap);

Updating Markers to Google Maps in google-map-react

onGoogleApiLoaded not invoked on locations data change, Is there any way to achieve this?
I tried to use useEffect to load markers but then I have to save map and maps objects in useRef as well as markers
Is there any easier way to achieve this?
import { useEffect, useRef } from 'react';
import GoogleMapReact from 'google-map-react';
export type SimpleMapProps = {
locations: any[];
};
export default function SimpleMap({ locations }: SimpleMapProps) {
const defaultProps =
locations.length > 0
? {
center: {
lat: locations[0].Lat,
lng: locations[0].Lon
},
zoom: 11
}
: {
center: {
lat: 0,
lng: 0
},
zoom: 11
};
const handleApiLoadData = (map: any, maps: any) => {
for (let i = 0; i < locations.length; i++) {
const { Lat, Lon, hn, cur, rate } = locations[i];
const marker = new maps.Marker({
animation: maps.Animation.DROP,
position: { lat: Lat, lng: Lon },
map
});
marker.customInfowindow = new maps.InfoWindow({
content: `<div>${hn} </br> (${cur} ${rate})</div>`
});
marker.addListener('click', () => {
marker.customInfowindow.open(map, marker);
});
}
};
return (
// Important! Always set the container height explicitly
<div style={{ height: '50vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{
key: 'XXXXXXXXXXXXXXX'
}}
center={defaultProps.center}
zoom={defaultProps.zoom}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => handleApiLoadData(map, maps)}
/>
</div>
);
}

can not move location and create marker mapbox react

this code is o create a marker using the value introduced by the user, and make this marker fixed.
but I don't even can create the marker, nothing happen.
it's stick in the initial location after rendering. I taught maybe it was a lat and lng order but I try that and it's keep loading.
I try also to remove flyTo but nothing changed
export default function Map() {
const mapContainer = useRef(null);
const [lng, setLng] = useState(-70.9);
const [lat, setLat] = useState(42.35);
const [zoom, setZoom] = useState(9);
const [searchValue, setSearchValue] = useState("");
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/streets-v11",
center: [lng, lat],
zoom: zoom,
});
map.addControl(new mapboxgl.NavigationControl(), "top-right");
map.on("move", () => {
setLng(map.getCenter().lng.toFixed(4));
setLat(map.getCenter().lat.toFixed(4));
setZoom(map.getZoom().toFixed(2));
});
}, []); // eslint-disable-line react-hooks/exhaustive-deps
function getCoordinates(placesContent) {
const { center, place_name } = placesContent.features[0];
return {
coordinates: center.reverse(),
name: place_name,
};
}
const changeMapCenter = async () => {
const map = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/streets-v11",
center: [lng, lat],
zoom: zoom,
});
return fetch(
`${MAPBOX_PLACES_API}${searchValue}${REST_PLACES_URL}`,
FETCH_HEADERS
)
.then((res) => res.json())
.then((apiData) => {
console.log("apidata=>", apiData);
const { coordinates } = getCoordinates(apiData);
console.log("coordinates=>", coordinates);
map.flyTo(coordinates);
new mapboxgl.Marker().setLngLat(coordinates).addTo(map);
});
};
const handleChange = (event) => {
setSearchValue(event.target.value);
};
return (
<div className="mapBox">
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
<div>
<label>create your spot collection</label>
<input
type="text"
id="spotLocation"
onChange={handleChange}
value={searchValue}
/>
<button onClick={changeMapCenter}>search and create </button>
</div>
</div>
<div className="map-container" ref={mapContainer} />
</div>
);
}
Try saving the map in a state and use setCenter
const [ customMap, setMap ] = useState({ lat: 0, lng: 0}) // set your own initial value
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/streets-v11",
center: [lng, lat],
zoom: zoom,
});
map.addControl(new mapboxgl.NavigationControl(), "top-right");
map.on("move", () => {
setLng(map.getCenter().lng.toFixed(4));
setLat(map.getCenter().lat.toFixed(4));
setZoom(map.getZoom().toFixed(2));
});
setMap(map);
}, []);
const handleChange = (event) => {
// i assume event.target.value contains the coordinates
// example 929292, 2929292
setSearchValue(event.target.value)
};
const onSubmit = () => {
let coordinates = searchValue.split(',')
customMap.setCenter({ lat: coordinates[0], lng: coordinates[1]});
}

Pass arbitrary callbacks/params in React

I want to pass callbacks through to a map component, and this requires being able to give any args I want. I try with
MapView.js:
import React, { Component } from 'react';
import { browserHistory } from 'react-router';
export default class MapView extends Component {
constructor(props){
super(props);
this.renderMap = this.renderMap.bind(this);
this.addMarkerToMap = this.addMarkerToMap.bind(this);
this.clickMarker = this.clickMarker.bind(this);
}
componentDidMount() {
this.renderMap();
}
renderMap() {
let map_data = {
zoom: this.props.zoom || 10,
center: this.props.center || {lat: 30.3, lng: -97.75} // default to Austin
};
let this_map = new google.maps.Map(this.refs.map, map_data);
let markers_data = this.props.markers_data || [];
markers_data.map(function(data) {
this.addMarkerToMap(data, this_map);
}.bind(this));
}
addMarkerToMap(data, the_map) {
let marker = new google.maps.Marker({
position: data.coordinates,
map: the_map
});
if (data.callback) {
let params = data.params || [];
marker.addListener('click', data.callback.bind(this, ...params));
}
return marker
}
clickMarker(item_id, pathname) {
// http://stackoverflow.com/questions/31079081/programmatically-navigate-using-react-router
browserHistory.push(
{
pathname: pathname,
query: { item_id: item_id } // https://stackoverflow.com/questions/36350644/how-can-i-pass-parameters-on-redirection-using-react-router
}
);
}
render() {
return (
<div>
<h3>{this.props.title}</h3>
<p>{this.props.description}</p>
<div style={ {height: 500, width: 500 } } ref="map" />
</div>
)
}
}
MapShowCustomers.js:
import React, {Component} from "react";
import { browserHistory } from 'react-router';
import MapView from './MapView';
export default class MapShowCustomers extends Component {
constructor(props){
super(props);
this.clickMarker2 = this.clickMarker2.bind(this);
this.exampleCallback = this.exampleCallback.bind(this);
}
clickMarker2(pathname, item_id) {
alert(pathname);
// http://stackoverflow.com/questions/31079081/programmatically-navigate-using-react-router
browserHistory.push(
{
pathname: pathname,
query: { item_id: item_id } // https://stackoverflow.com/questions/36350644/how-can-i-pass-parameters-on-redirection-using-react-router
}
);
}
exampleCallback(text) {
console.log(text)
if (text) {
alert(text);
} else {
alert("it worked anyway");
}
}
render() {
let titleText = "This one to show customers for restaurant employees...more of a map example";
let description = "Notice the usage of the 'center' prop...by overwriting the default center, this one shows up in Illinois (center={ {lat: 40.3, lng: -88.75} } )"
let coordinates = {lat: 40.3, lng: -88.75};
let markersData = [
// {callback: this.clickMarker2, args: ['/profile-customer', 2], coordinates: {lat: 40.25, lng: -88.65}},
// {callback: this.clickMarker2, args: ['/profile-customer', 7], coordinates: {lat: 40.35, lng: -88.85}},
// {callback: this.clickMarker2, args: ['/profile-customer', 6], coordinates: {lat: 40.37, lng: -88.78}}
{callback: this.exampleCallback, params: ["blah"], pathname: '/profile-customer', item_id: 1, coordinates: {lat: 40.25, lng: -88.65}},
{callback: this.exampleCallback, params: ["blah"], pathname: '/profile-customer', item_id: 13, coordinates: {lat: 40.35, lng: -88.85}},
{callback: this.exampleCallback, pathname: '/profile-customer', item_id: 37, coordinates: {lat: 40.37, lng: -88.78}}
];
{/* look at the center prop for how to pass props...in GoogleMap component it defaults to Austin */}
return (
<div>
<MapView markers_data={markersData} center={coordinates} title={titleText} description={description}/>
</div>
);
}
}
I try pass {callback: this.exampleCallback, pathname: '/profile-customer', item_id: 37, coordinates: {lat: 40.37, lng: -88.78}} through without params and see exampleCallback alert "it worked anyway" by doing
if (data.callback) {
let params = data.params || [];
marker.addListener('click', data.callback.bind(this, ...params));
}
but now I see this:
and it wants to alert [object Object] instead of "it worked anyway". This code can be seen at this repo (to try it, use npm i; npm start).
In addMarkerToMap:
if (data.callback) {
let params = data.params || [undefined];
marker.addListener('click', data.callback.bind(this, ...params));
}
The ...params unpacks an array into separate parameters, for example running data.callback.bind(this, ...[1, 2, 3) unpacks to data.callback.bind(this, 1, 2, 3). This is a newer feature in ES6. By defaulting to [undefined], you end up unpacking to data.callback.bind(this, undefined), which gets ignored if your callback doesn't need arguments.

google-maps-react user location not working

I am trying to display the user location on the map using google-maps-react. I followed the fullstack tutorial, but I just can't seem to display the user location. I will display my Map.js Component below. Please help me point out what I am doing wrong. Thank you.
import React, { Component } from 'react'
import ReactDOM from 'react-dom';
class Map extends Component {
constructor(props) {
super(props);
const {lat, lng} = this.props.initialCenter;
this.state = {
currentLocation: {
lat: lat,
lng: lng
}
}
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.google !== this.props.google) {
this.loadMap();
}
if (prevState.currentLocation !== this.state.currentLocation) {
this.recenterMap();
}
}
recenterMap() {
const map = this.map;
const curr = this.state.currentLocation;
const google = this.props.google;
const maps = google.maps;
if (map) {
let center = new maps.LatLng(curr.lat, curr.lng)
map.panTo(center)
}
}
componentDidMount() {
if (this.props.centerAroundCurrentLocation) {
if (navigator && navigator.geolocation) {
navigator.geolocation.getCurrentPosition((pos) => {
const coords = pos.coords;
this.setState({
currentLocation: {
lat: coords.latitude,
lng: coords.longitude
}
})
})
}
}
this.loadMap();
}
loadMap() {
if (this.props && this.props.google) {
// google is available
const {google} = this.props;
const maps = google.maps;
const mapRef = this.refs.map;
const node = ReactDOM.findDOMNode(mapRef);
let {initialCenter, zoom} = this.props;
const {lat, lng} = initialCenter;
const center = new maps.LatLng(lat, lng);
const mapConfig = Object.assign({}, {
center: center,
zoom: zoom
})
this.map = new maps.Map(node, mapConfig);
}
}
render() {
const style = {
width: '100vw',
height: '100vh'
}
return (
<div ref='map' style={style}>
Loading map...
</div>
)
}
}
Map.propTypes = {
google: React.PropTypes.object,
zoom: React.PropTypes.number,
initialCenter: React.PropTypes.object,
centerAroundCurrentLocation: React.PropTypes.bool
}
Map.defaultProps = {
zoom: 13,
// San Francisco, by default
initialCenter: {
lat: 37.774929,
lng: -122.419416
},
centerAroundCurrentLocation: false
}
export default Map

Categories

Resources