2

In my one of react component,

import React, { Component } from 'react';
import './css/addItem.css';

class AddItem extends Component {
    constructor(props) {
        super(props);
    } 
    showPosition(position) {
        console.log("Latitude: ",position.coords.latitude+
        " Longitude: ",position.coords.longitude);
    }
    getGeoLocation() {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(this.showPosition);
        } else { 
            console.log("Geolocation is not supported by this browser.");
        }       
    }
    render() {
        return (
            <div>
                .....
                .....
                <button onClick={this.getGeoLocation}>Get GeoLocation</button>
            </div>
        );
    }
}

export default AddItem;

My it says Cannot read property 'showPosition' of undefined.

GeoLocation is simply not working.

Being new to React, I tried,

this.showPosition = this.showPosition.bind(this);

in constructor.

But that did not help.

Could some one please explain what am I doing wrong and how to fix it ?

StrugglingCoder
  • 4,781
  • 16
  • 69
  • 103
  • 4
    bind this: `this.getGeoLocation = this.getGeoLocation.bind(this)` because you want to access `this` (correct class instance) inside that function. – Mayank Shukla Mar 16 '18 at 09:45
  • I'd recommend to make all funcitons in the arrow function mode so that using `this.myMethod` is easier, i.e. to make them `showPosotion = () =>` and `getGeoLocation = () =>` – Marson Mao Mar 16 '18 at 09:50
  • You can get more information from here https://stackoverflow.com/questions/38334062/why-do-you-need-to-bind-a-function-in-a-constructor – Suresh Ponnukalai Mar 16 '18 at 10:09

1 Answers1

2

Your function getGeoLocation is called with another context. React does not bind your event listeners or any another function automatically. So you receive this === undefined in getGeoLocation. To fix this issue, you could use this.getGeoLocation = this.getGeoLocation.bind(this) in your constructor function, or just use class properties with an arrow function. For example:

import React, { Component } from 'react';
import './css/addItem.css';

class AddItem extends Component {
    constructor(props) {
        super(props);
    } 
    showPosition(position) {
        console.log("Latitude: ",position.coords.latitude+
        " Longitude: ",position.coords.longitude);
    }
    // We use class property with arrow function to bind context:
    getGeoLocation = () => {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(this.showPosition);
        } else { 
            console.log("Geolocation is not supported by this browser.");
        }       
    }
    render() {
        return (
            <div>
                .....
                .....
                <button onClick={this.getGeoLocation}>Get GeoLocation</button>
            </div>
        );
    }
}

export default AddItem;
Nik
  • 2,170
  • 1
  • 14
  • 20
  • Thanks for the prompt response. This is where my understanding breaks down. What do you mean by getGeoLocation is called with another context. Could you please explain? Does it get called by the button object context? Does that mean every function almost needs to be bounded in the constructor? Please explain. Sorry for being so naive about it. – StrugglingCoder Mar 16 '18 at 09:49
  • 1
    @StrugglingCoder Every function of your class that needs to use `this` in its body needs to be explicitly bound to `this`. You bound the function that does not use `this` and didn't do it for the function that actually needs to bound. Read up here [How functions work in javascript](https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/). If you use babel you can just use the public class fields syntax to get around this: `getGeoLocation = () => {...}`. Functions in this syntax will always be bound to `this` automatically. – trixn Mar 16 '18 at 10:01
  • @Nikita M. your snippet does not have the updated information. please update it. – Suresh Ponnukalai Mar 16 '18 at 10:08
  • I extended my answer with explanation why you receive undefined, and added comment to snippet – Nik Mar 16 '18 at 10:23