0

I am working on Google Maps rendering in ReactJS. For that, I am using 'react-google-maps' library. The logical flow is; at the page load, get the user's location and plot them on the map. A user is provided with navigation links to hit different URL. To handle the navigation, I am using React router. The user's location is identified in componentWillMount() then the state is set accordingly and the map is rendered in render(). The problem is that render() gets called before completing componentWillMount(), it gets the null values and it fails. This situation only occurs in client-side routing and not in server-side rendering.

To restrict the way of execution, I made the componentWillMount() as an async method where it waits until the user's location is determined. Still, it was not helpful.

state = {
        homeLocation: {},
        coordinates: []
    }

async componentWillMount(props) {
        const { lat,lng } = await this.getcurrentLocation();
        this.setState({
            homeLocation:{
                lat: lat, 
                lng: lng
            }
        })
    }

getcurrentLocation() {

        if (window.navigator && window.navigator.geolocation) {
          return new Promise((resolve, reject) => {
            window.navigator.geolocation.getCurrentPosition(pos => {
              const coords = pos.coords;
              resolve({
                lat: coords.latitude,
                lng: coords.longitude
              });
            });
          });
        }
        return {
          lat: 0,
          lng: 0
        };
      }
render(){

   <MapWithAMarker
   // necessary parameters
  />
}

//Routers
const AppRouter = () => (
    <Router>
        <div>
            <Switch>
                <Route path="/" component={MapHomeLocation} exact={true}/>
                <Route path="/location/:locationType" component={MapSelectedLocation}/>
                <Route component={Notfound}/>
            </Switch>
        </div>

    </Router>
);


The expected result is that coordinates should be determined first then render() should get called. In server-side routing(i.e. using anchor tags instead of <Link>) it works as expected.
Swapnil
  • 801
  • 3
  • 19
  • 42

3 Answers3

1

Call the getcurrentLocation() in the state itself.

state = {
        homeLocation: this.getcurrentLocation(),
        coordinates: []
    }



getcurrentLocation() {

        if (window.navigator && window.navigator.geolocation) {
          return new Promise((resolve, reject) => {
            window.navigator.geolocation.getCurrentPosition(pos => {
              const coords = pos.coords;
              resolve({
                lat: coords.latitude,
                lng: coords.longitude
              });
            });
          });
        }
        return {
          lat: 0,
          lng: 0
        };
      }
render(){

   <MapWithAMarker
   // necessary parameters
  />
}

//Routers
const AppRouter = () => (
    <Router>
        <div>
            <Switch>
                <Route path="/" component={MapHomeLocation} exact={true}/>
                <Route path="/location/:locationType" component={MapSelectedLocation}/>
                <Route component={Notfound}/>
            </Switch>
        </div>

    </Router>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
  • If you don't mind asking the code snippet to set the values in state. Since getcurrentLocation() returns two values, how can I assign them to homeLocation object in state. – Swapnil Mar 23 '19 at 07:24
1

you should check like that if data is there in that then only give value.

if data && data.length > 0 ? data : null

Mehul Jariwala
  • 886
  • 1
  • 9
  • 19
1

Never do fetching operations in componentWillMount(), instead use componentDidMount() since calling setState() would re-render the component, you probably will see new data appears on your map.

DarkSuniuM
  • 2,523
  • 2
  • 26
  • 43
Kianoosh
  • 56
  • 1
  • 8