React/redux:渲染嵌套对象属性时出错
我有一个通过 RabbitMQ 接收数据的 react/redux 前端。当消息到达时,我们的消息处理程序将分派一个操作,例如
PRODUCT_DETAILS_LOADED
,该操作会更新商店并使用产品详细信息呈现相应的组件。这 95% 有效,但如果我尝试显示嵌套对象属性,我会收到错误:
无法读取未定义的属性 <prop>
。
我对此做了一些研究。大多数答案都表明发生了竞争条件,并且组件试图在属性“准备好”之前呈现它们。我不明白为什么会这样,因为我没有进行 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 }
}
最后,reducer:
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 语句显示正确的数据,但 bomb 之后的
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) 确保组件在状态更新完成之前根本不加载。此逻辑将在 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
}
这是 react 默认行为的一部分,也是 redux 问题。有关 setState 的工作原理以及为什么不应将其视为同步代码的更多信息,请参阅 https://reactjs.org/docs/react-component.html#setstate 。