【问题标题】:React - Unable to setState inside a Promise thenReact - 然后无法在 Promise 中设置状态
【发布时间】:2019-06-01 15:01:40
【问题描述】:

我正在尝试在 Promise 的 then() 中设置状态,但状态值没有得到保存,并且在 then() 之外无法访问。

下面是更新的代码:

handleSelect = location => {
  this.setState({ location });
  geocodeByAddress(
    location
  )
  .then(results => getLatLng(results[0]))
  .then(latLng => {
    this.setState({
      location_latitude: latLng.lat,
      location_longitude: latLng.lng,
    })
    console.log(this.state.location_latitude); // returns the correct value
  })
  console.log(this.state.location_latitude); // returns null (the originally declared value)
}

如果我 console.log(this.state.location_latitude) 我得到一个 null 值。但是,如果我在 then() 块中使用 console.log,我会得到正确的值。这种情况下如何设置状态?

更新说明:

为了给这里的整个逻辑提供一个更好的上下文:我正在使用一个 Google Places 自动完成组件,它允许用户从下拉列表中选择一个位置。当用户从下拉列表中选择一个位置时,将调用上述方法handleSelect。然后我使用geocodeByAddress 方法提取用户选择的地点的纬度和经度,这是一个承诺。然后我需要检索纬度和经度并相应地设置状态,稍后用于发送到数据库。我还不能将值提交到数据库,因为用户需要填写其他表单输入(它们也存储在状态中),一旦他点击提交,我将提交所有状态元素单次调用后端。所以,我不想用componentDidMount() 更新任何内容,或者没有任何内容需要更新以使用componentDidUpdate()。无论如何,我只能将状态值存储在 geocodeByAddress 的 then 中(如果我在这里错了,请纠正我)。所以,我必须能够修改 then 块内的状态值。

【问题讨论】:

  • 您的 console.log(location_latitude) 记录为 null 在哪里?
  • 这个函数调用的其余代码在哪里?需要整个反应类方法的代码。在某处你丢失了this 上下文
  • 如果您丢失了this 上下文,请不要忘记在构造函数中将您的函数绑定到this
  • 如果你试图访问这个状态来获得它的价值并首先在某个地方使用,你应该使用ComponentDidMount。这样当您访问它时,该值就存在于状态中。

标签: javascript reactjs promise


【解决方案1】:

问题是当您set-state 之后您无法立即看到状态结果。这就是console.log 返回null 的原因。确保您的console.logrender block 中。这是因为 set-state 操作是 asynchronous 并且是批处理以提高性能。这在 setState 的文档中进行了解释。 看看这个 => Why is setState in reactjs Async instead of Sync?

【讨论】:

  • 谢谢!是的,我确实意识到价值实际上正在更新,而不是立即更新。我能够解决这个问题。谢谢!
【解决方案2】:

您需要将函数上下文绑定到当前类/组件。试试下面的东西。创建一个类似“callSetState”的函数,将其与 this 绑定,然后在调用时将值作为参数传递给它。

import React, { Component } from 'react';
class Test extends Component{
    constructor() {
        super()
        this.callSetState = this.callSetState.bind(this);
    }

    callSetState(latitude, longitude) { 
        this.setState({
            location_latitude: latitude,
            location_longitude: longitude,
        })
    }

/* Call this func in your class and call callSetState which is already bound to your component in constructor */

    // geocodeByAddress(location)
    //     .then(results => getLatLng(results[0]))
    //     .then(latLng => this.callSetState(latLng.lat, latLng.lng));

}

【讨论】:

    【解决方案3】:

    这显然是您的数据调用没有反应的问题。

    您的反应代码看起来不错,但我建议吐出代码。

    1) service.js 文件 - 这会执行您的查询并返回数据或返回错误。

    2) 位置组件,componentDidMount() 或 useEffect(() => {}, []) 获取数据并更新 state/useState()

    为了给你一个代码 sn-p 我需要你提供一个latLang & results 的控制台日志。

    非常感谢??

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-02
      • 1970-01-01
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多