I'm trying to add the transform property to my create component. Then inside the transform, I call a function to get the lat and long based on the address parameters.
But before the geodecoder is done the dataprovider is already sending data to the API.
Is there anyway so that I can let the transform know the data is al set to be send?
Also kinda new to React. So, maybe I'm missing something obvious. Here's my code so far:
import * as React from "react";
import {Create, ReferenceArrayInput, SelectArrayInput, SimpleForm, TextInput} from 'react-admin';
import Geocode from "react-geocode";
Geocode.setApiKey("MY_API_KEY");
Geocode.setRegion("nl");
export const StoreCreate = props => {
function getLatLong(data) {
const addressObject = data.address;
if ((addressObject.postal_code.length >= 6 &&
addressObject.postal_code.length <= 7) &&
addressObject.street_name.length > 0 &&
addressObject.housenumber.length > 0
) {
const regex = /^[1-9][0-9]{3}[\s]?[A-Za-z]{2}$/i;
if (regex.test(addressObject.postal_code)) {
const address = addressObject.street_name + ' ' + addressObject.housenumber + ' ' + addressObject.postal_code;
Geocode.fromAddress(address).then(
response => {
const {lat, lng} = response.results[0].geometry.location;
console.log({
address: {
...addressObject, ...{
lat: lat,
lng: lng
}
}
});
return {
address: {
...addressObject, ...{
lat: lat,
lng: lng
}
}
};
},
error => {
console.error(error);
}
);
}
}
}
const transform = (data) => ({
...data,
...getLatLong(data)
});
return (
<Create {...props} transform={transform}>
<SimpleForm>
<TextInput source="name"/>
<TextInput source="email" type="email"/>
<TextInput source="address.street_name"/>
<TextInput source="address.housenumber"/>
<TextInput source="address.postal_code"/>
<TextInput source="address.city"/>
<ReferenceArrayInput source="store_types" reference="store-types">
<SelectArrayInput source="name"/>
</ReferenceArrayInput>
<TextInput source="address.lat"/>
<TextInput source="address.lng"/>
</SimpleForm>
</Create>
);
};
First, the getLatLong function does not return the promise.
function getLatLong(data) {
const addressObject = data.address;
if ((addressObject.postal_code.length >= 6 &&
addressObject.postal_code.length <= 7) &&
addressObject.street_name.length > 0 &&
addressObject.housenumber.length > 0
) {
const regex = /^[1-9][0-9]{3}[\s]?[A-Za-z]{2}$/i;
if (regex.test(addressObject.postal_code)) {
const address = addressObject.street_name + ' ' + addressObject.housenumber + ' ' + addressObject.postal_code;
return Geocode.fromAddress(address).then(
response => {
const {lat, lng} = response.results[0].geometry.location;
console.log({
address: {
...addressObject, ...{
lat: lat,
lng: lng
}
}
});
return {
address: {
...addressObject, ...{
lat: lat,
lng: lng
}
}
};
},
error => {
console.error(error);
throw error;
}
);
}
}
return {};
}
Then, you should use it correctly in your tranform function:
const transform = (data) => getLatLong(data).then((longData) => ({
...data,
...longData
}));
Related
I'm using google-maps-react library for maps in my react application, and I'm adding search address functionality in my application and facing CORS error.
Error:
Autocomplete.js
import React, { Component } from 'react';
import styled from 'styled-components';
const Wrapper = styled.div`
position: relative;
align-items: center;
justify-content: center;
width: 100%;
padding: 20px;
text-align:center;
`;
class AutoComplete extends Component {
constructor(props) {
super(props);
this.clearSearchBox = this.clearSearchBox.bind(this);
}
componentDidMount({ map, mapApi } = this.props) {
const options = {
// restrict your search to a specific type of result
types: ['address'],
// restrict your search to a specific country, or an array of countries
// componentRestrictions: { country: ['gb', 'us'] },
};
this.autoComplete = new mapApi.places.Autocomplete(
this.searchInput,
options,
);
this.autoComplete.addListener('place_changed', this.onPlaceChanged);
this.autoComplete.bindTo('bounds', map);
}
componentWillUnmount({ mapApi } = this.props) {
mapApi.event.clearInstanceListeners(this.searchInput);
}
onPlaceChanged = ({ map, addplace } = this.props) => {
const place = this.autoComplete.getPlace();
if (!place.geometry) return;
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
addplace(place);
this.searchInput.blur();
};
clearSearchBox() {
this.searchInput.value = '';
}
render() {
return (
<Wrapper>
<input
className="search-input"
ref={(ref) => {
this.searchInput = ref;
}}
type="text"
onFocus={this.clearSearchBox}
placeholder="Enter a location"
/>
</Wrapper>
);
}
}
export default AutoComplete;
Google Map Component:
const MyGoogleMap = () => {
const [apiReady, setApiReady] = useState(false);
const [map, setMap] = useState(null);
const [mapApi, setMapApi] = useState(null);
const [address, setAddress] = useState();
const [zoom, setZoom] = useState();
const [center, setCenter] = useState([]);
const [lat, setLat] = useState();
const [lng, setLng] = useState();
const [places, setPlaces] = useState();
const [draggable, setDraggable] = useState();
const setCurrentLocation = () => {
if ('geolocation' in navigator) {
navigator.geolocation.getCurrentPosition(position => {
console.log('position.coords: ', position.coords.longitude);
console.log("[position.coords.latitude, position.coords.longitude]: ", [position.coords.latitude, position.coords.longitude])
setCenter([position.coords.latitude, position.coords.longitude]);
setLat(position.coords.latitude);
setLng(position.coords.longitude);
});
}
};
useEffect(() => {
setCurrentLocation();
}, []);
const handleApiLoaded = (map, maps) => {
console.log('map, maps: ', map, maps);
// use map and maps objects
if (map && maps) {
setApiReady(true);
setMap(map);
setMapApi(maps);
}
};
const _generateAddress = () => {
const geocoder = new mapApi.Geocoder();
geocoder.geocode({ location: { lat: lat, lng: lng } }, (results, status) => {
console.log(results);
console.log(status);
if (status === 'OK') {
if (results[0]) {
setZoom(12);
setAddress(results[0].formatted_address);
} else {
window.alert('No results found');
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
};
const onMarkerInteraction = (childKey, childProps, mouse) => {
setDraggable(true);
setLat(mouse.lat);
setLng(mouse.lng);
};
const onMarkerInteractionMouseUp = (childKey, childProps, mouse) => {
setDraggable(true);
_generateAddress();
};
const _onChange = ({ center, zoom }) => {
setZoom(zoom);
setCenter(center);
};
const _onClick = value => {
setLat(value.lat);
setLng(value.lng);
};
const addPlace = place => {
setPlaces([place]);
setLat(place.geometry.location.lat());
setLng(place.geometry.location.lng());
_generateAddress();
};
return (
<div style={{ height: '442px', width: '100%' }}>
{apiReady && <Autocomplete map={map} mapApi={mapApi} addplace={addPlace} />}
<GoogleMapReact
zoom={4}
center={center}
bootstrapURLKeys={{
key: 'API_KEY',
libraries: ['places', 'geometry'],
}}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) =>
handleApiLoaded(map, maps)
}
></GoogleMapReact>
</div>
);
}
I'm following this article to integrate Google Maps with search
I am having trouble using setStates. I stored an array of markers for my Google Map in my state and I am using a for loop to iterate through each marker in order to change the position state of the marker using Google's Geocode API.
Here is my state:
state = {
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {},
markers: [
{
name: "Costco Wholesale",
address: "9151 Bridgeport Rd, Richmond, BC V6X 3L9",
position: { lat: 0, lng: 0 },
placeID: 'ChIJWc2NzuF0hlQRDu0NNhdQCjM'
} //just trying to get this one to work first before I add in the others
],
busy: []
};
Here is the function(declared inside the class):
findLatLong(){
for(let i = 0; i < this.state.markers.length; i++){
Geocode.fromAddress(this.state.markers[i].address).then(
response => {
const { lati, lngi } = response.results[0].geometry.location;
this.state.markers[i].position.setState({lat: lati, lng: lngi})
}
);
}
}
As you can see, I am passing the address contained in the same array element into the .fromAddress function and then using setState to set the lat and lng to the returned value.
I later call the function after the map renders but before the markers do:
<Map
google={this.props.google}
zoom={14}
style={mapStyles}
initialCenter={{ lat: 49.166590, lng: -123.133569 }}
>
{this.findLatLong}
{this.state.markers.map((marker, index) => (
<Marker
key={index}
onClick={this.onMarkerClick}
name={marker.name}
position={marker.position}
/>
))}
However marker's position state is not changing and is instead remaining as the filler values I passed during the initial state declaration.
Full code if it helps:
import React, { Component } from 'react';
import { Map, GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';
import Geocode from 'react-geocode';
const key = '';
Geocode.setApiKey(key);
const mapStyles = {
width: '100%',
height: '100%'
};
export class MapContainer extends Component {
state = {
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {},
markers: [
{
name: "Costco Wholesale",
address: "9151 Bridgeport Rd, Richmond, BC V6X 3L9",
position: { lat: 0, lng: 0 },
placeID: 'ChIJWc2NzuF0hlQRDu0NNhdQCjM'
}
],
busy: []
};
findLatLong(){
for(let i = 0; i < this.state.markers.length; i++){
Geocode.fromAddress(this.state.markers[i].address).then(
response => {
const { lati, lngi } = response.results[0].geometry.location;
this.state.markers[i].position.setState({lat: lati, lng: lngi})
}
);
}
}
componentDidMount() {
this.getList();
}
getList = () => {
fetch('/api/getList')
.then(res => res.json())
.then(percent => this.setState({ busy: percent }))
}
onMarkerClick = (props, marker, e) =>
this.setState({
selectedPlace: props,
activeMarker: marker,
showingInfoWindow: true
});
onClose = props => {
if (this.state.showingInfoWindow) {
this.setState({
showingInfoWindow: false,
activeMarker: null
});
}
};
render() {
return (
<Map
google={this.props.google}
zoom={14}
style={mapStyles}
initialCenter={{ lat: 49.166590, lng: -123.133569 }}
>
{this.findLatLong}
{this.state.markers.map((marker, index) => (
<Marker
key={index}
onClick={this.onMarkerClick}
name={marker.name}
position={marker.position}
/>
))}
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
onClose={this.onClose}
>
<div>
<h4>{this.state.selectedPlace.name}</h4>
<h4>{this.state.busy}</h4>
</div>
</InfoWindow>
</Map>
);
}
}
Thank you in advance!
Attempt to fix #1
.then(
response => {
const { lati, lngi } = response.results[0].geometry.location;
this.setState(oldState => {
const newMarkers = [oldState.markers];
const modifiedMarker = newMarkers[i];
modifiedMarker.lat = lati;
modifiedMarker.lng = lngi;
return {oldState, markers: [newMarkers]};
//How do i implement the modifiedMarkers?
})
UPDATE
Actually it is better if you mutate the state just once and not inside the loop
findLatLong(){
const newMarkers = [...this.state.markers]
for(let i = 0; i < this.state.markers.length; i++){
Geocode.fromAddress(this.state.markers[i].address).then(
response => {
const { lati, lngi } = response.results[0].geometry.location;
newMarkers[i].position.lat = lati;
newMarkers[i].position.lng = lngi;
}
);
}
this.setState(oldState => {
return { ...oldState, markers: [...newMakers] };
});
}
That's no how you mutate the state, it should be something like this:
this.setState(oldState => {
const newMakers = [...oldState.makers];
const modifiedElement = newMakers[i];
modifiedElement.lat = lati;
modifiedElement.lng = lngi;
return { ...oldState, makers: [...newMakers] };
});
I have a question about react-native MapViewDirection with the expo.
I have my result received from the onReady function inside MapViewDirection.
I want to display the distance and duration field to the user.
onReady={result => {
console.log(result)
}};
I want to declare I am learning and am using someone else's code to practice. Below is full code:
import React, { Component } from 'react';
import { Dimensions, StyleSheet } from 'react-native';
import MapView from 'react-native-maps';
import MapViewDirections from 'react-native-maps-directions';
const { width, height } = Dimensions.get('window');
const ASPECT_RATIO = width / height;
const LATITUDE = 40.3788;
const LONGITUDE = -105.5143;
const LATITUDE_DELTA = 0.0192;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
const GOOGLE_MAPS_APIKEY = 'AIzaSyAkwAlX2w0S3ba6OxBqr13JGDuYIi5GRZ8';
class Example extends Component {
constructor(props) {
super(props);
this.state = {
coordinates: [
{
latitude:40.3788,
longitude:-105.5143,
},
],
};
this.mapView = null;
}
onMapPress = (e) => {
this.setState({
coordinates: [
...this.state.coordinates,
e.nativeEvent.coordinate,
],
});
}
render() {
return (
<MapView
initialRegion={{
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}}
style={StyleSheet.absoluteFill}
ref={c => this.mapView = c}
onPress={this.onMapPress}
>
{this.state.coordinates.map((coordinate, index) =>
<MapView.Marker key={`coordinate_${index}`} coordinate={coordinate} />
)}
{(this.state.coordinates.length >= 2) && (
<MapViewDirections
origin={this.state.coordinates[0]}
waypoints={ (this.state.coordinates.length > 2) ? this.state.coordinates.slice(1, -1): null}
destination={this.state.coordinates[this.state.coordinates.length-1]}
apikey={GOOGLE_MAPS_APIKEY}
strokeWidth={3}
strokeColor="hotpink"
optimizeWaypoints={true}
onStart={(params) => {
console.log(`Started routing between "${params.origin}" and "${params.destination}"`);
}}
onReady={result => {
console.log(result);
this.mapView.fitToCoordinates(result.coordinates, {
edgePadding: {
right: (width / 20),
bottom: (height / 20),
left: (width / 20),
top: (height / 20),
}
});
}}
onError={(errorMessage) => {
// console.log('GOT AN ERROR');
}}
/>
)}
</MapView>
);
}
}
export default Example;
Using the below given code you can get the distance between two locations using there latitude & longitude. We are using google distance matrix api here to get distance.
getDistanceOneToOne(lat1, lng1, lat2, lng2)
{
const Location1Str = lat1 + "," + lng1;
const Location2Str = lat2 + "," + lng2;
let GOOGLE_API_KEY = "API_KEY"
let ApiURL = "https://maps.googleapis.com/maps/api/distancematrix/json?"
let params = `origins=${Location1Str}&destinations=${Location2Str}&key=${GOOGLE_API_KEY}`; // you need to get a key
let finalApiURL = `${ApiURL}${encodeURI(params)}`;
this.getDistance(finalApiURL).then((getDistance) => {
console.log('Distance charges',getDistance);
if (getDistance.status == "OK")
{
let value = getDistance.rows[0].elements[0].distance.text; //Distance
let time = getDistance.rows[0].elements[0].duration.value; //time
}
});
}
getDistance = (url) => {
return this.getDistanceCall(url)
}
getDistanceCall = (url) => {
return fetch(url, {
method: 'GET',
})
.then((response) => { return response.json(); })
.catch((error) => {
return error;
});
}
When I use Polyline it gives me this error:
attempt to invoke interface method 'java.util.iterator java.util.list.iterator()' on a null object
At first, I thought I made something wrong or I mis-used google-map API so I tried with some hard-coded coords (as shown in my code below) but without any progress.
The code will run fine if I remove the Polyline part.
I googled hoping to find any solution but without any success also.
some info my about dev platform:
expo version 2.19.1
yarn version 1.16.0
Node version 10.15.2
Testing on a physical device with android PI installed.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Permissions, MapView } from 'expo'
// import Polyline from '#mapbox/polyline'
import { Polyline } from 'react-native-maps'
const locations = require('./locations.json')
export default class App extends React.Component {
state = {
latitude: null,
longitude: null,
locations: locations
}
componentDidMount() {
this.GetLocations()
}
GetLocations = async () => {
const { status } = await Permissions.getAsync(Permissions.LOCATION)
if (status !== 'granted') {
const response = await Permissions.askAsync(Permissions.LOCATION)
}
navigator.geolocation.getCurrentPosition(
({ coords: { latitude, longitude }}) => this.setState({ latitude, longitude}, this.mergeCoords),
(err) => console.log(`Error: ${err}`)
)
const { locations: [sampleLocation] } = this.state
this.setState({
desLatitude: sampleLocation.coords.latitude,
desLongitude: sampleLocation.coords.longitude,
}, this.mergeCoords)
}
mergeCoords = () => {
const { latitude, longitude, desLatitude, desLongitude } = this.state
const hasStartAndEnd = ( latitude !== null && desLatitude !== null )
// if the line have start and end
if (hasStartAndEnd) {
const concatStart = `${latitude},${longitude}`
const concatEnd = `${desLatitude},${desLongitude}`
this.getDirections(concatStart, concatEnd)
}
}
async getDirections(startLoc, desLoc) {
try {
// const res = await fetch(`https://maps.googleapis.com/maps/api/directions/json?key=MY_API_KEY&origin=${startLoc}&destination=${desLoc}`)
// const resJson = await res.json()
// const points = Polyline.decode(resJson.routes[0].overview_polyline.points)
// const coords = points.map( point => {
// return {
// latitude: point[0],
// longitude: point[1]
// }
// })
const coords = {
latitude: 31.262353,
longitude: 29.989506,
}
console.log("point, coords: ", coord)
this.setState({coords})
} catch(err) {
console.log('Error: ', err)
}
}
render() {
const { latitude, longitude, coords } = this.state
if (latitude) {
return (
<MapView
style={{ flex: 1 }}
showsUserLocation
initialRegion={{
latitude,
longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
<MapView.Polyline
strokeWidth={2}
strokeColor="red"
coordinates={coords}
/>
</MapView>
)
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>We need your permissions !!</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
//use condional rendering
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Permissions, MapView } from 'expo'
// import Polyline from '#mapbox/polyline'
import { Polyline } from 'react-native-maps'
const locations = require('./locations.json')
export default class App extends React.Component {
state = {
latitude: null,
longitude: null,
locations: locations,
direct : false
}
componentDidMount() {
this.GetLocations()
}
GetLocations = async () => {
const { status } = await Permissions.getAsync(Permissions.LOCATION)
if (status !== 'granted') {
const response = await Permissions.askAsync(Permissions.LOCATION)
}
navigator.geolocation.getCurrentPosition(
({ coords: { latitude, longitude }}) => this.setState({ latitude, longitude},
this.mergeCoords),
(err) => console.log(`Error: ${err}`)
)
const { locations: [sampleLocation] } = this.state
this.setState({
desLatitude: sampleLocation.coords.latitude,
desLongitude: sampleLocation.coords.longitude,
}, this.mergeCoords)
}
mergeCoords = () => {
const { latitude, longitude, desLatitude, desLongitude } = this.state
const hasStartAndEnd = ( latitude !== null && desLatitude !== null )
// if the line have start and end
if (hasStartAndEnd) {
const concatStart = `${latitude},${longitude}`
const concatEnd = `${desLatitude},${desLongitude}`
this.getDirections(concatStart, concatEnd)
}
}
async getDirections(startLoc, desLoc) {
try {
// const res = await fetch(`https://maps.googleapis.com/maps/api/directions/json?
key=MY_API_KEY&origin=${startLoc}&destination=${desLoc}`)
// const resJson = await res.json()
// const points = Polyline.decode(resJson.routes[0].overview_polyline.points)
// const coords = points.map( point => {
// return {
// latitude: point[0],
// longitude: point[1]
// }
// })
const coords = {
latitude: 31.262353,
longitude: 29.989506,
}
console.log("point, coords: ", coord)
this.setState({coords, direct:true})
} catch(err) {
console.log('Error: ', err)
}
}
render() {
const { latitude, longitude, coords } = this.state
if (latitude) {
return (
<MapView
style={{ flex: 1 }}
showsUserLocation
initialRegion={{
latitude,
longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
{this.state.direct &&
<MapView.Polyline
strokeWidth={2}
strokeColor="red"
coordinates={coords}
/>}
</MapView>
)
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>We need your permissions !!</Text>
</View>
)
}
}
I have read the other questions related to this and tried implementing what the answers were on there.
They recommended adding /*global google */ - did not work
Next was to add const google = window.google; - did not work
I will post the code below and the error.
The error is happening where new google.maps is being called
Map.js:
/* global google */
import { default as React, Component } from 'react';
import raf from 'raf';
import canUseDOM from 'can-use-dom';
const google = window.google;
import { withGoogleMap, GoogleMap, Circle, InfoWindow, Marker } from 'react-google-maps';
import withScriptjs from 'react-google-maps/lib/async/withScriptjs';
const googleMapURL =
'https://maps.googleapis.com/maps/api/js?v=3.27&libraries=places,geometry&key=AIzaSyA7XEFRxE4Lm28tAh44M_568fCLOP_On3k';
const geolocation =
canUseDOM && navigator.geolocation
? navigator.geolocation
: {
getCurrentPosition(success, failure) {
failure("Your browser doesn't support geolocation.");
},
};
const GeolocationExampleGoogleMap = withScriptjs(
withGoogleMap(props =>
<GoogleMap defaultZoom={8} center={props.center}>
{props.center &&
<InfoWindow position={props.center}>
<div>User's Location</div>
</InfoWindow>}
{props.center &&
<Circle
center={props.center}
radius={props.radius}
options={{
fillColor: 'red',
fillOpacity: 0.2,
strokeColor: 'red',
strokeOpacity: 1,
strokeWeight: 1,
}}
/>}
>
{props.markers.map((marker, index) => {
const onClick = () => props.onMarkerClick(marker);
const onCloseClick = () => props.onCloseClick(marker);
return (
<Marker
key={index}
position={marker.position}
title={(index + 1).toString()}
onClick={onClick}
>
{marker.showInfo &&
<InfoWindow onCloseClick={onCloseClick}>
<div>
<strong>
{marker.content}
</strong>
<br />
<em>The contents of this InfoWindow are actually ReactElements.</em>
</div>
</InfoWindow>}
</Marker>
);
})}
</GoogleMap>,
),
);
function generateInitialMarkers() {
const southWest = new google.maps.LatLng(-31.203405, 125.244141);
const northEast = new google.maps.LatLng(-25.363882, 131.044922);
const lngSpan = northEast.lng() - southWest.lng();
const latSpan = northEast.lat() - southWest.lat();
const markers = [];
for (let i = 0; i < 5; i++) {
const position = new google.maps.LatLng(
southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random(),
);
markers.push({
position,
content: 'This is the secret message'.split(' ')[i],
showInfo: false,
});
}
return markers;
}
export default class GeolocationExample extends Component {
constructor(props) {
super(props);
super(props);
this.state = {
center: null,
content: null,
radius: 6000,
markers: generateInitialMarkers(),
};
const isUnmounted = false;
handleMarkerClick = this.handleMarkerClick.bind(this);
handleCloseClick = this.handleCloseClick.bind(this);
}
handleMarkerClick(targetMarker) {
this.setState({
markers: this.state.markers.map((marker) => {
if (marker === targetMarker) {
return {
...marker,
showInfo: true,
};
}
return marker;
}),
});
}
handleCloseClick(targetMarker) {
this.setState({
markers: this.state.markers.map((marker) => {
if (marker === targetMarker) {
return {
...marker,
showInfo: false,
};
}
return marker;
}),
});
}
componentDidMount() {
const tick = () => {
if (this.isUnmounted) {
return;
}
this.setState({ radius: Math.max(this.state.radius - 20, 0) });
if (this.state.radius > 200) {
raf(tick);
}
};
geolocation.getCurrentPosition(
(position) => {
if (this.isUnmounted) {
return;
}
this.setState({
center: {
lat: position.coords.latitude,
lng: position.coords.longitude,
},
content: 'Location found using HTML5.',
});
raf(tick);
},
(reason) => {
if (this.isUnmounted) {
return;
}
this.setState({
center: {
lat: 60,
lng: 105,
},
content: `Error: The Geolocation service failed (${reason}).`,
});
},
);
}
componentWillUnmount() {
this.isUnmounted = true;
}
render() {
return (
<GeolocationExampleGoogleMap
googleMapURL={googleMapURL}
loadingElement={<div style={{ height: '100%' }}>loading...</div>}
containerElement={<div style={{ height: '100%' }} />}
mapElement={<div style={{ height: '100%' }} />}
center={this.state.center}
content={this.state.content}
radius={this.state.radius}
onMarkerClick={this.handleMarkerClick}
onCloseClick={this.handleCloseClick}
markers={this.state.markers}
/>
);
}
}
You are loading async script. When you initialize google constant there is no google object. You can solve this by using 'ref' for map component. Ref callback fired when google object exists. For example:
<GoogleMap defaultZoom={8} center={props.center} ref={()=>{props.onMapLoad}}>...</GoogleMap>
...
constructor(props) {
...
this.onMapLoad = this.onMapLoad.bind(this)
}
...
onMapLoad() {
/*init markers and all objects with "google" here*/
}
...
<GeolocationExampleGoogleMap
onMapLoad={this.onMapLoad}
...
/>
and, of course, do not init google const, use just google object instead,