【问题标题】:React state is called before receiving value from API [duplicate]在从 API 接收值之前调用反应状态 [重复]
【发布时间】:2019-02-27 18:59:01
【问题描述】:

我正在尝试从 API 获取数据并将其放入我的状态,然后再将其呈现在组件上。

但是,在将任何值放入其中之前,会一直调用空状态。

代码如下:

const cookies = new Cookies();

class ProductDetails extends Component {

state = {product:null}

componentWillMount(){
    this.getSelectedProduct()
}
getSelectedProduct(){
    var selected = cookies.get('SelectedProduct')
    Axios.get('http://localhost:1002/products/' + selected)
    .then(ok=>{
        console.log(ok.data)
        this.setState({product:ok.data})
        console.log(this.state.product[0].ProductName)
    })
}
renderContent(){
    console.log(this.state.product)
    if(this.state.product !== [] ){
        const {ProductName, ProductPrice, Description, Brand, Color, ScreenSize, RAM, Storage, Stock} = this.state.product[0]
        return([
            ProductName,
            ProductPrice,
            Description, 
            Brand, 
            Color, 
            ScreenSize, 
            RAM, 
            Storage, 
            Stock
        ])
    }
}
render(){
    return(
        <div >
            <h3>{this.renderContent().ProductName}</h3>

        </div>
    )
}
}
export default ProductDetails

【问题讨论】:

  • 将条件改为 if(this.state.product && this.state.product.length ){
  • 我不是 100% 的问题是什么,因为您的代码乍一看还不错。但是this.setState 是异步的,所以当您尝试console.log 第一个产品名称时,它还不存在。
  • 如果您认为 console.log 没有打印正确的值。 setState 是异步的
  • 是的,我也认为问题是因为 setState 是异步的。我正在寻找解决方法。不,以这种方式更改 if else 条件是行不通的。它仍然给出“未定义”错误。
  • 你的代码没问题。你是在谈论设置状态后的console.log吗? setState() 异步不是问题,它是一个特性。你必须围绕它塑造你的应用行为

标签: javascript reactjs api asynchronous


【解决方案1】:

这就是 React 的工作方式——setState 是异步的,它不会阻止组件在设置状态之前渲染,即使您从 componentWillMount 执行此操作也是如此。

在您的render 方法中,检查product 是否已设置并仅在设置时调用renderContent

您可以改为显示“请稍候”消息或微调器。

例子:

render() {
    if (this.state.product === null) {


    return(
        <div >
            <h3>{
                this.state.product === null ? 
                "loading data, please wait" :
                this.renderContent().ProductName
            }</h3>
        </div>
    )
}

请注意: componentWillMount 已弃用,并且在更新的 React 版本中不可用。你应该改用componentDidMount

【讨论】:

    【解决方案2】:

    我同意之前的回答,您应该使用初始状态作为模型,因此给状态乘积一个空数组的值。但是,如果您仍想在初始状态下定义null,您可以在返回渲染方法之前进行检查。

    render(){
      if (!Array.isArray(this.state.product) {
        return null // or something else such a loading icon or similar.
      }
    
      return(
        <div >
          Your rendered content here
          ...
        </div>
      )
    }
    

    参见isArray的参考页面:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2017-01-18
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      相关资源
      最近更新 更多