3

I'm trying to show Google Map with centering the map based on latitude and longitude which are returned by Geolocation. However, the map shows as the default value and not get rendered by Geolocation values. I set latitude and longitude in component state and trying to re-render the component after the state is updated. But it does not work. Below is my code.

MapView.js

import React, { Component } from 'react'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps'
import MapComponent from './MapComponent'

class MapView extends Component {
  constructor(props){
    super(props)
    this.state = {
      currentLatLng: {
        lat: 0,
        lng: 0
      },
      isMarkerShown: false
    }
  }

  componentWillUpdate(){
    this.getGeoLocation()
  }

  componentDidMount() {
    this.delayedShowMarker()
  }

  delayedShowMarker = () => {
    setTimeout(() => {
      this.getGeoLocation()
      this.setState({ isMarkerShown: true })
    }, 5000)
  }

  handleMarkerClick = () => {
    this.setState({ isMarkerShown: false })
    this.delayedShowMarker()
  }

  getGeoLocation = () => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        position => {
          this.setState({
            lat: position.coords.latitude,
            lng: position.coords.longitude
          })
        }
      )
    } else {
      error => console.log(error)
    }
  }

  render() {
    return (
      <MapComponent
        isMarkerShown={this.state.isMarkerShown}
        onMarkerClick={this.handleMarkerClick}
        currentLocation={this.state.currentLatLng}
      />
    )
  }
}

export default MapView;

MapComponent.js

import React, { Component } from 'react'
import { compose, withProps } from 'recompose'
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from 'react-google-maps'

const MapComponent = 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
)((props) =>
  <GoogleMap
    defaultZoom={8}
    defaultCenter={{ lat: props.currentLocation.lat, lng: props.currentLocation.lng }}
  >
    {props.isMarkerShown && <Marker position={{ lat: props.currentLocation.lat, lng: props.currentLocation.lng }} onClick={props.onMarkerClick} />}
  </GoogleMap>
)

export default MapComponent
shinyatk
  • 855
  • 11
  • 28

2 Answers2

8

In fact map is not centered since currentLatLng is not getting updated, you might want something like this:

getGeoLocation = () => {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                position => {
                    console.log(position.coords);
                    this.setState(prevState => ({
                        currentLatLng: {
                            ...prevState.currentLatLng,
                            lat: position.coords.latitude,
                            lng: position.coords.longitude
                        }
                    }))
                }
            )
        } else {
            error => console.log(error)
        }
    }

instead of original getGeoLocation function

Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • 1
    Your solutions works perfectly! I have not thought about "prevState" and merging with the current state. Thank you so much! – shinyatk Jun 10 '18 at 23:11
0

According to w3.org, the current location can be obtained with:

function showMap(position) {
    // Show a map centered at (position.coords.latitude, position.coords.longitude).
    console.log(position.coords.latitude);
    console.log(position.coords.longitude);
  }

  // One-shot position request.
  navigator.geolocation.getCurrentPosition(showMap);

This links Geolocation API: Geolocation API w3.org

This worked for me, location high accuracy.