简体   繁体   中英

React setState is undefined?

I have this simple get location from browser navigator function to a weather api. I don't understand why both consoles of latitude and longitude works, but when I do setState its yelling at me saying uncaught TypeError: Cannot read property 'setState' of undefined.

To be more clear these 2 consoles i get the positions

console.log(position.coords.latitude)
console.log(position.coords.longitude)

but this is saying cant pass undefined things to setState

this.setState({lat:position.coords.latitude,lon:position.coords.longitude})

 import React from 'react'; import axios from 'axios'; import WeatherGadget from './weather.component' export default class WeatherApi extends React.Component { constructor(props) { super(props); this.state = { city: null,lat:0,lon:0,wind:0,weather:0,icon:null }; } componentDidMount() { const location = ()=>{navigator.geolocation.getCurrentPosition(function(position) { console.log(position.coords.latitude) console.log(position.coords.longitude) this.setState({lat:position.coords.latitude,lon:position.coords.longitude}) //Uncaught TypeError: Cannot read property 'setState' of undefined })} location(); const url = `https://api.openweathermap.org/data/2.5/onecall?lat=${this.state.lat}&lon=${this.state.lon}&appid=8821HIDDEN4e9d78`; const getWeather = async ()=>{ let res = await axios.get(url) const weatherObj = res.data; console.log("===",weatherObj) const currentWeather = weatherObj.current.temp const windSpeed = weatherObj.current.wind_speed const icon = weatherObj.current.weather[0].icon this.setState({wind:windSpeed,weather:currentWeather,icon:icon}) } getWeather() } render() { return ( <div > <WeatherGadget city={this.state.city} wind ={this.state.wind} weather={this.state.weather} icon={this.state.icon}/> </div> ) } }

It is very simple in navigator object you cannot access this object because it has reference of window object So for that I use navigator object in promise and if navigator gives me the latitude and longitude then i resolve my promise if not reject the promise and return the promise.

In ComponentDidMount I called the function using await because it return me the promise after that I have value then I set the state

And Called the other getWeather Function

import React from "react";
import axios from "axios";
// import WeatherGadget from './weather.component'

export default class WeatherApi extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      city: null,
      lat: 0,
      lon: 0,
      wind: 0,
      weather: 0,
      icon: null
    };
  }


  async componentDidMount() {
    const location = await this.location();
    location && this.setState({ lat: location.lat, lon: location.long });
    location && this.getWeather();
  }
  location = () => {
   //return the promise that contain the navigator object
    return new Promise((resolve, reject) => {
      try {
        navigator.geolocation.getCurrentPosition(position => {
          resolve({
            lat: position.coords.latitude,
            long: position.coords.longitude
          });
        });
      } catch (error) {
        let temp = {
          lat: 24.8607,
          long: 67.0011
        };
        reject(temp);
      }
    });
  };
//calling weather api
  getWeather = async () => {
    const url = `https://api.openweathermap.org/data/2.5/onecall?lat=${
      this.state.lat
    }&lon=${this.state.lon}&appid=8821HIDDEN4e9d78`;
    console.log("url", url);
    try {
      const res = await axios.get(url);
      if (res) {
        console.log("res", res.data)
        const weatherObj = res.data;
        console.log("===", weatherObj);
        const currentWeather = weatherObj.current.temp;
        const windSpeed = weatherObj.current.wind_speed;
        const icon = weatherObj.current.weather[0].icon;
        this.setState({ wind: windSpeed, weather: currentWeather, icon: icon });
      }
    } catch (error) {
      console.log("error", error)
    }
  };
  render() {
    return (
      <div>
        {/* <WeatherGadget city={this.state.city}  wind ={this.state.wind} weather={this.state.weather} icon={this.state.icon}/> */}
        <p> Lat: {this.state.lat}</p>
        <p> Lng: {this.state.lon}</p>
        <p> Weather: {this.state.weather}</p>
        <p>Wind: {this.state.wind}</p>

      </div>
    );
  }
}

I just had to create the function outside component mount an simply call it inside like below

 import React from 'react'; import axios from 'axios'; import WeatherGadget from './weather.component' export default class WeatherApi extends React.Component { constructor(props) { super(props); this.state = { city: null, lat: 0, lon: 0, wind: 0, weather: 0, icon: null }; } location = () => { navigator.geolocation.getCurrentPosition((position) => { this.setState({ lat: position.coords.latitude, lon: position.coords.longitude }) //Uncaught TypeError: Cannot read property 'setState' of undefined const url = `https://api.openweathermap.org/data/2.5/onecall?lat=${this.state.lat}&lon=${this.state.lon}&appid=8821a871fa3513caf66ad2e8ab4e9d78`; console.log("====url", url) const getWeather = async () => { let res = await axios.get(url) const weatherObj = res.data; console.log("===", weatherObj) const currentWeather = weatherObj.current.temp const windSpeed = weatherObj.current.wind_speed const icon = weatherObj.current.weather[0].icon this.setState({ wind: windSpeed, weather: currentWeather, icon: icon }) } getWeather() }) } componentDidMount() { this.location(); } render() { return ( <div > <WeatherGadget city={this.state.city} wind={this.state.wind} weather={this.state.weather} icon={this.state.icon} /> </div> ) } }

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