![](/img/trans.png)
[英]How to update React props when web component attributes are updated async?
[英]How to get React/recompose component updated when props are changed?
我正在編寫這個產品列表組件,但我正在為狀態而苦苦掙扎。 列表中的每個產品本身都是一個組件。 一切都按預期渲染,除了在 prop 更改時組件不會更新。 我正在使用 recompose 的withPropsOnChange()
希望每次更改shouldMapOrKeys
的道具時shouldMapOrKeys
觸發它。 然而,這永遠不會發生。
讓我展示一些代碼:
import React from 'react'
import classNames from 'classnames'
import { compose, withPropsOnChange, withHandlers } from 'recompose'
import { addToCart } from 'utils/cart'
const Product = (props) => {
const {
product,
currentProducts,
setProducts,
addedToCart,
addToCart,
} = props
const classes = classNames({
addedToCart: addedToCart,
})
return (
<div className={ classes }>
{ product.name }
<span>$ { product.price }/yr</span>
{ addedToCart ?
<strong>Added to cart</strong> :
<a onClick={ addToCart }>Add to cart</a> }
</div>
)
}
export default compose(
withPropsOnChange([
'product',
'currentProducts',
], (props) => {
const {
product,
currentProducts,
} = props
return Object.assign({
addedToCart: currentProducts.indexOf(product.id) !== -1,
}, props)
}),
withHandlers({
addToCart: ({
product,
setProducts,
currentProducts,
addedToCart,
}) => {
return () => {
if (addedToCart) {
return
}
addToCart(product.id).then((success) => {
if (success) {
currentProducts.push(product.id)
setProducts(currentProducts)
}
})
}
},
}),
)(Product)
我認為這addToCart
但addToCart
函數返回一個 Promise。 現在,它總是解析為true
。
另一個說明: currentProducts
和setProducts
分別是一個屬性和一個方法,來自一個保存購物車數據的類(模型)。 這也很好用,不會拋出異常或顯示意外行為。
這里的預期行為是:將產品添加到購物車並更新currentProducts
列表后, addedToCart
道具將更改其值。 我可以確認currentProducts
正在按預期更新。 但是,這是未到達代碼的一部分(我在該行中添加了一個斷點):
return Object.assign({
addedToCart: currentProducts.indexOf(product.id) !== -1,
}, props)
由於我已經為另一個組件使用了類似的結構——主要區別在於我“聽”的一個道具是由withState()
定義的——我想知道我在這里遺漏了什么. 我的第一個想法是問題是由currentProducts
的直接更新引起的,這里:
currentProducts.push(product.id)
所以我嘗試了一種不同的方法:
const products = [ product.id ].concat(currentProducts)
setProducts(products)
不過,這在執行過程中沒有任何改變。
我正在考慮使用withState
而不是withPropsOnChange
。 我想那會奏效。 但在采取這種方式之前,我想知道我在這里做錯了什么。
正如我想象的那樣,使用withState
幫助我實現了預期的行為。 不過,這絕對不是我想要的答案。 無論如何,我在這里發布它願意幫助面臨類似問題的其他人。 我仍然希望找到一個答案來解釋為什么我的第一個代碼盡管沒有拋出任何錯誤但仍然不起作用。
export default compose(
withState('addedToCart', 'setAddedToCart', false),
withHandlers({
addToCart: ({
product,
setProducts,
currentProducts,
addedToCart,
}) => {
return () => {
if (addedToCart) {
return
}
addToCart(product.id).then((success) => {
if (success) {
currentProducts.push(product.id)
setProducts(currentProducts)
setAddedToCart(true)
}
})
}
},
}),
lifecycle({
componentWillReceiveProps(nextProps) {
if (this.props.currentProducts !== nextProps.currentProducts ||
this.props.product !== nextProps.product) {
nextProps.setAddedToCart(nextProps.currentProducts.indexOf(nextProps.product.id) !== -1)
}
}
}),
)(Product)
這里的變化是:
withPropsOnChange
,其用來處理addedToCart
“計算”;withState
來為addedToCart
聲明和創建一個 setter ;setAddedToCart(true)
開始調用addToCart
處理程序中的setAddedToCart(true)
;lifecycle
添加componentWillReceiveProps
事件以在道具更改時更新addedToCart
。其中一些更新基於此答案。
我認為您面臨的問題是由於withPropsOnChange
的返回值。 你只需要做:
withPropsOnChange([
'product',
'currentProducts',
], ({
product,
currentProducts,
}) => ({
addedToCart: currentProducts.indexOf(product.id) !== -1,
})
)
與withProps
, withPropsOnChange
會自動將返回的對象合並到 props 中。 不需要Object.assign()
。
參考: https : //github.com/acdlite/recompose/blob/master/docs/API.md#withpropsonchange
ps:如果可以的話,我也會將條件替換為currentProducts.includes(product.id)
。 它更明確。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.