React / redux:错误渲染嵌套对象属性

时间:2019-06-13 13:34:27

标签: reactjs redux react-redux

我有一个react / redux前端,可以通过RabbitMQ接收数据。当消息到达时,我们的消息处理程序将调度一个操作,例如PRODUCT_DETAILS_LOADED,用于更新商店并使用产品详细信息呈现适当的组件。这是95%的工作方式,但是如果我尝试显示嵌套对象的属性,则会收到错误消息:Cannot read property <prop> of undefined

我对此做了一些研究。大多数答案都表明正在发生竞争状况,并且组件正在尝试在“就绪”之前渲染属性。我不知道怎么回事,因为我没有进行REST调用。我已经有消息队列中的数据,并且已经更新了商店。此外,render函数中的console.log将显示嵌套属性的正确值。这是我的大部分ProductDetails组件:

const mapStateToProps = state => {
  return { product: state.productDetail };
}

class ProductDetails extends Component {

  render() {
    console.log(this.props.product.availability.forsale);  //This will correctly show 'true' or 'false'
    return (
            <div> 
                <h3>Product Details Page</h3>
                <h5>Details for {this.props.product.name}: </h5>
                <div>
                  Name:  {this.props.product.name}
                  <br/>
                  SKU:  {this.props.product.sku}
                  <br/>
                  Available:  {this.props.product.availability.forsale} //This throws an error
                  <br/> 
                  {/*Price: {this.props.product.price.$numberDecimal} //This would also throw an error
                  <br/>*/}
                  Description: {this.props.product.description}              
                </div>
                <Link to="/">Back to Home Page</Link> 
            </div>
    )
  }
}

const Details = connect(mapStateToProps, null)(ProductDetails);
export default Details;

以下是处理程序中的代码段,当收到产品详细信息消息时会触发该代码段:

  } else if(json.fields.routingKey === 'product.request.get') {   
    if(json.status === 'success') {
     let payload = json.data;
      store.dispatch(productDetailsLoaded(payload));
    } 

这是调度动作的功能:

export function productDetailsLoaded(details) {
  return { type: PRODUCT_DETAILS_LOADED, productDetail: details }
}

最后,是减速器:

  if(action.type === PRODUCT_DETAILS_LOADED) {
    return Object.assign({}, state, {
      productDetail: action.productDetail
    });
  }

我已经看到一些答案,这些建议建议类似以下内容以防止错误:let av = this.props.product.availability ? this.props.product.availability.forsale : '';。这对我不起作用。虽然确实可以防止错误,但我将显示空白值。这不是我的选择;我必须在详细信息页面上显示正确的信息,而不仅仅是“非错误”信息。

有人可以帮助我了解发生了什么吗?为什么console.log语句在炸弹之后立即显示正确的数据却显示render语句?我该如何解决?

谢谢!

编辑:这是我要渲染的对象:

{ 
    assets: {
        imgs: "https://www.zzzzzzz.com/content/12626?v=1551215311"
    }
    availability: {
        forsale: true, 
        expires: "2025-12-29T05:00:00.000Z"
    }
    createdAt: "2015-01-25T05:00:00.000Z"
    description: "his is a fake description"
    modifiedAt: "2019-05-28T04:00:00.000Z"
    name: "Product Name"
    price: {
        $numberDecimal: "59.95"
    }
    sku: "ZZZZ"
    "title ": "Product Title"
    _id: "5ceec82aa686a03bccfa67cc"
}

1 个答案:

答案 0 :(得分:1)

您试图在对象准备就绪之前对其进行访问。引发错误的两个位置是子属性。因此,对于其他所有内容,初始值都是“ undefined”,您的应用程序可以使用该值,但是一旦尝试读取undefined属性,它将引发错误。

有三种解决方案: 1)确保在状态完成更新之前完全不加载组件。此逻辑将在ProductDetails的父组件中处理。

如果没有选择1),请执行以下一项操作:

2)设置productDetails:为null,然后在您的组件中

render() {
    console.log(this.props.product.availability.forsale);  //This will correctly show 'true' or 'false'
    if (!this.props.product) return <div />;
    return (
            // what you have above
    )
  }
}

const Details = connect(mapStateToProps, null)(ProductDetails);
export default Details;

3)设置默认状态形状,类似以下内容:

{ 
    assets: {
        imgs: null
    }
    availability: {
        forsale: null, 
        expires: null
    }
    createdAt: null
    description: null
    modifiedAt: null
    name: null
    price: {
        $numberDecimal: null
    }
    sku: null
    "title ": null
    _id: null
}

这是redux问题的一部分,它是react默认行为的一部分。有关setState的工作原理以及为什么不应将其视为同步代码的更多信息,请参见https://reactjs.org/docs/react-component.html#setstate