3

Please i have this problem with my react class,i'm trying to update my state but i'm get this error "Cannot read property 'setState' of undefined" ..I have tried every solution online,but no luck

here is the code

export default class PageBackground extends Component{
    constructor(props) {
            super(props);

            this.state={
                lat         :'nothing',
                longi       :''
            };
            this.getLocation=this.getLocation.bind(this);
            }


        componentWillMount() {
            this.getLocation();
        }
        getLocation () {

            fetch('http://freegeoip.net/json/')
             .then((res)=>res.json())
             .then(function (objec){this.setState({lat:objec.latitude,longi:objec.longitude});})
             .catch((err)=>console.log("didn't connect to App",err))
             console.log(this.state.lat)
        }

        render(){
            return(
                <p>{this.state.lat}</p>
                )
            }
        }
John Anisere
  • 513
  • 1
  • 3
  • 13

3 Answers3

7

The function () { ... } syntax won't maintain the this reference from the context. Use an arrow function instead:

then(() => {
    this.setState({lat: objec.latitude, longi: objec.longitude})
})

Another option is to add .bind(this) after function () { }.

Or, just save this to a local variable and use it inside the function:

var self = this;
fetch('http://freegeoip.net/json/')
         .then((res)=>res.json())
         .then(function (objec){self.setState({lat:objec.latitude,longi:objec.longitude});})
         .catch((err)=>console.log("didn't connect to App",err))
         console.log(this.state.lat)

However, arrow functions were introduced exactly for this kind of problems.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • thank you very much.This worked but i want to know why? i read the arrow function doesn't work well with 'this' why is this situation different? – John Anisere Oct 17 '17 at 10:54
  • and why do we even have to bind all methods in we create in es6 class in our constructor? – John Anisere Oct 17 '17 at 10:55
  • 1
    @JohnAnisere The answer to the first question is that arrow functions capture `this` from the surrounding code, therefore you don't have to bind `this` to them manually. They work in the way you would expect. The other question is more complicated. You are talking about the problem when class methods are used as "loose" (first class) functions. The methods are not bound automatically to their instance and must be bound manually. – Sulthan Oct 17 '17 at 10:58
1

Try this out:

   getLocation () {
            var self = this;
            fetch('http://freegeoip.net/json/')
             .then(function (objec) {
               console.log(objec);
               self.setState({lat: objec.latitude, longi: objec.longitude})
             })
            .catch(function (error) {
               console.log(error);
            });
        }
Saad Khan
  • 108
  • 1
  • 1
  • 10
1

The problem here is, you are trying to accesss this in a different scope.

Whenever we pass a function() {} as a callback it creates it's own scope. Use arrow function's instead.

() => { 'your code here'; }

Arrow functions share the scope of its parent.

getLocation = () => {
    fetch('https://freegeoip.net/json/')
        .then(res => res.json())
        .then((objec) => {
            this.setState({ lat: objec.latitude, longi: objec.longitude });
        })
        .catch(err => console.log("didn't connect to App", err));
    console.log(this.state.lat);
}
Rajendra kumar Vankadari
  • 2,247
  • 1
  • 16
  • 16