我有一个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"
}
答案 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。