简体   繁体   中英

React: Uncaught TypeError: Cannot read properties of undefined (reading 'setState')

I am new to learning React and I want to fetch something by making an API call which seems to not work for me. For the following code, I am getting an error in the console mentioned in the title.

The error is showing in the fetch statement for the below code and I am not been able to rectify it. What I am doing here is fetching the latitude and longitude of a position and passing it to a URL to fetch the weather.

import React, { Component } from "react"

class WeatherData extends Component{
  constructor(props){
    super(props);
    this.state ={
      weatherReport:[]
    };
  }

  componentDidMount() {
    navigator.geolocation.getCurrentPosition(function(position) {
      const lat =  position.coords.latitude;
      const lon = position.coords.longitude;
    fetch('https://api.openweathermap.org/data/2.5/weather?lat='+{lat}+'&lon='+{lon}+'&appid=xxxxxxxxxxxxxxxxxxxxxxx')
    .then(response => response.json())
    .then(data => this.setState({ weatherReport: data.main}));
    });
    
}
  render(){
    const  { weatherReport }  = this.state;

    
    return(
      <div>
          {weatherReport.temp}
      </div>
    );
  }
}

export default WeatherData;

Any help will be appreciated.

You are using a function using the function keyword when getting the geolocation - this gives a new this reference to anything inside its scope, including the arrow function and its contents. Use a fat arrow function, which binds the current this to its child blocks, to maintain the correct scope when using callbacks.

Also, not sure why you are chaining an object in the url like that:

componentDidMount() {
    navigator.geolocation.getCurrentPosition((position) => { // this line
        const lat = position.coords.latitude;
        const lon = position.coords.longitude;
        fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=xxxxxxxxxxxxxxxxxxxxxxx`
          .then(response => response.json())
          .then(data => this.setState({
            weatherReport: data.main
          }));
        });
    }

This is due to the difference between using the function keyword, and the "fat arrow" syntax ( => )

The function keyword created a new " this context" while the fat arrow inherits the parent context. In other words, when you use function , the value of the this keyword becomes something new inside of that function, whereas, with => , it remains the same as it was outside of the function.

You can read more about the this keyword here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

And more on the difference between function and => can be found here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions


So, instead of writing this:
getCurrentPosition(function(position) {

You should write this:
getCurrentPosition((position) => {

Full example:

import React, { Component } from "react"

class WeatherData extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weatherReport: []
    };
  }

  componentDidMount() {
    navigator.geolocation.getCurrentPosition((position) => { // <- this is what has changed
      const lat = position.coords.latitude;
      const lon = position.coords.longitude;
      fetch('https://api.openweathermap.org/data/2.5/weather?lat=' + { lat } + '&lon=' + { lon } + '&appid=xxxxxxxxxxxxxxxxxxxxxxx')
        .then(response => response.json())
        .then(data => this.setState({ weatherReport: data.main }));
    });
  }

  render() {
    const { weatherReport } = this.state;

    return (
      <div>
        {weatherReport.temp}
      </div>
    );
  }
}

export default WeatherData;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM