【问题标题】:Not able to set state using this.setState in react无法在反应中使用 this.setState 设置状态
【发布时间】:2020-11-01 18:39:17
【问题描述】:

我正在使用 js 的地理定位 API 来获取坐标。 long 和 lat 值正在设置。我通过 console.log 检查了状态变量经度和纬度,尽管调用了 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

【问题讨论】:

  • 好吧,你没有在你的代码中显示控制台日志,这绝对是关键,位置。 setState 是异步的,当你尝试记录它时它可能还没有准备好
  • getCurrentPosition()异步 。就像你不能在送达之前吃披萨一样,你也不能访问尚未收到的数据
  • 状态变量在 React 组件的下一个渲染周期中更新。检查here。您可能在方法componentDidMount() 中使用控制台日志,它不会在设置后立即显示更新的值。在componentDidUpdate() 方法中添加控制台日志,您将看到更新后的状态变量值。
  • 你建议我应该怎么做来设置经度和纬度?
  • @dhruvtailor,最可能的方法是让您的componentDidMount 异步,然后等待地理位置。

标签: javascript reactjs


【解决方案1】:

在一切之后,你已经尝试过了,去把你的 componentDidMount() 变成一个 async 函数。

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

【讨论】:

  • 正如我上面提到的,这种方法在 this.setState 处出错
  • @dhruvtailor ,我看到回调不是我遇到的大多数情况下的匿名函数,所以我刚刚编辑了,必须为你工作。
【解决方案2】:

由于navigator.geolocation.getCurrentPosition 是异步的,您可以像这样使用async/await 功能:

声明获取当前位置的方法,await 获取结果并设置状态。

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
  })
}

然后在componentDidMount调用这个方法

componentDidMount(){
  this.getPosition();
}

【讨论】:

  • 嗯,您尝试过第二种变体吗?在函数中包含setState?这还是不行吗?
  • @Apostolos,在componentDidMount 我猜getPosition() 又是异步的,这仍然没有解决。
  • 抱歉是正确的,我们需要以不同的方式处理函数声明。检查更新的答案
  • @dhruvtailor 试试我更新的答案,它应该可以工作。
  • 实际上你不能在 react 方法之外声明一个变量。它给出了错误。
【解决方案3】:

我刚刚在@Apostolos 答案中进行了一些修改。

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)
        
    }

【讨论】:

    【解决方案4】:

    如果您不打算进一步链接它,则不必将 getCurrentPosition 转换为 Promise。在我看来,最干净的解决方案就是在这里使用回调函数。

    与您在问题中所做的重要区别在于,我将 this.setState 调用移到了 getCurrentPosition 回调中。

    请注意,您必须使用arrow function 来保持getCurrentPosition 回调的this 值与componentDidMount 函数内部的值相同。

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

    有关{coords: {longitude, latitude}} 语法的更多信息,我想将您重定向到MDN Destructing assignment - Object destructing 页面。

    【讨论】:

      猜你喜欢
      • 2018-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 2018-06-12
      • 1970-01-01
      相关资源
      最近更新 更多