简体   繁体   中英

Not able to set state using this.setState in react

I am using the geolocation API of js to get coordinate. The long and lat values are getting set. I checked through console.log but the state variable longitude and latitude are not getting set despite calling the setState.

import React from 'react';

class Weather extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            longitude : '',
            latitude : ''
        }
    }
    
    componentDidMount(){
        var long = 'a';
        var lat = 'b';
        var a = function(pos){
            long = pos.coords.longitude
            lat = pos.coords.latitude
        }
        
        navigator.geolocation.getCurrentPosition(a);
        this.setState({
            longitude: long,
            latitude: lat
        })
    }
    render(){
        return (
            <div className="container">
                <div className="city">
                    <h1>City Name</h1>
                        <h3>lon:{this.state.longitude}</h3>
                        <h3>{this.state.latitude}</h3>
                </div>
                <div className="icon">
                    
                </div>
            </div>
        )
    }
}
export default Weather

Since navigator.geolocation.getCurrentPosition is asynchronous, you could use async/await functionality like this:

Declare your method where you get the current position, await for the result anf then set your state.

getPosition = async () => {

  let promise = new Promise(function (resolve, reject) {
    navigator.geolocation.getCurrentPosition(resolve, reject);
  });

  let pos = await promise;

  this.setState({
    longitude: pos.coords.longitude,
    latitude: pos.coords.latitude
  })
}

and then in componentDidMount call this method

componentDidMount(){
  this.getPosition();
}

After everything, you have already tried, go and make your componentDidMount() an async function.

import React from 'react';

class Weather extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            longitude : '',
            latitude : ''
        }
    }
    
    async componentDidMount(){
        var long = 'a';
        var lat = 'b';
        var a = function(pos){
            long = pos.coords.longitude
            lat = pos.coords.latitude
        }
        
        await navigator.geolocation.getCurrentPosition(a);
        this.setState({
             longitude: long,
             latitude: lat
        })
    }
    render(){
        return (
            <div className="container">
                <div className="city">
                    <h1>City Name</h1>
                        <h3>lon:{this.state.longitude}</h3>
                        <h3>{this.state.latitude}</h3>
                </div>
                <div className="icon">
                    
                </div>
            </div>
        )
    }
}
export default Weather

I just worked it out using some modification in @Apostolos answer.

componentDidMount(){
        var long = 'a';
        var lat = 'b';
        
        async function getPosition(t) {
            let promise = new Promise(function (resolve, reject) {
              navigator.geolocation.getCurrentPosition(resolve, reject);
            });
            let pos = await promise;

            t.setState({
              longitude: pos.coords.longitude,
              latitude: pos.coords.latitude
            })
          }
          getPosition(this)
        
    }

You don't have to convert the getCurrentPosition into a promise if you are not going to chain it any further. The cleanest solution in my opinion would be to just use the callback function here.

The important difference with what you already do inside the question is that I move the this.setState call inside the getCurrentPosition callback.

Note that you must use an arrow function to keep the this value for the getCurrentPosition callback the same as inside the componentDidMount function.

componentDidMount() {
  navigator.geolocation.getCurrentPosition(
    ({coords: {longitude, latitude}}) => this.setState({longitude, latitude})
  );
}

For more info about the {coords: {longitude, latitude}} syntax, I'd like to redirect you to the MDN Destructing assignment - Object destructing page.

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