Reactjs 如何在道具更改时更新React/recompose组件?
我正在写这个产品列表组件,我正在与美国进行斗争。列表中的每个产品本身就是一个组件。所有内容都按预期进行渲染,但道具更改时组件不会更新。我正在使用recompose的Reactjs 如何在道具更改时更新React/recompose组件?,reactjs,recompose,Reactjs,Recompose,我正在写这个产品列表组件,我正在与美国进行斗争。列表中的每个产品本身就是一个组件。所有内容都按预期进行渲染,但道具更改时组件不会更新。我正在使用recompose的with propsonChange()希望每次shouldMapworkeys中的道具更改时都会触发它。然而,这种情况从未发生过 让我展示一些代码: import React from 'react' import classNames from 'classnames' import { compose, withPropsOnC
with propsonChange()
希望每次shouldMapworkeys
中的道具更改时都会触发它。然而,这种情况从未发生过
让我展示一些代码:
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)
因为我已经为另一个组件使用了类似的结构——主要的区别是我正在“听”的一个道具是由withState()
——定义的,我想知道我在这里缺少了什么。我的第一个想法是问题是由直接更新currentProducts
引起的,这里:
currentProducts.push(product.id)
所以我尝试了一种不同的方法:
const products = [ product.id ].concat(currentProducts)
setProducts(products)
但在执行过程中,这并没有改变任何事情
我正在考虑使用带有state的
而不是带有propsonchange的。我想那会有用的。但在这样做之前,我想知道我做错了什么。正如我想象的那样,使用和state
帮助我实现了预期的行为。但这绝对不是我想要的答案。无论如何,我把它贴在这里是为了帮助其他面临类似问题的人。我仍然希望找到一个答案来解释为什么我的第一个代码没有工作,尽管它没有抛出错误
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)
这里的变化是:
删除了with propsonchange
,它用于处理addedToCart
的“计算”李>
添加了和state
,以声明和创建addedToCart
的setter李>
当产品成功添加到购物车时,开始在addToCart
处理程序内调用setAddedToCart(true)
李>
通过重组的生命周期
添加了组件将接收道具
事件,以在道具更改时更新addedToCart
其中一些更新是基于。我认为您面临的问题是由于withPropsOnChange的返回值造成的。您只需执行以下操作:
withPropsOnChange([
“产品”,
“当前产品”,
], ({
产品,,
当前产品,
}) => ({
addedToCart:currentProducts.indexOf(product.id)!=-1,
})
)
与使用withProps
时一样,withPropsOnChange
将自动将返回的对象合并到props中。不需要对象.assign()
参考:
p、 如果可以的话,我也会将条件替换为currentProducts.includes(product.id)
。它更明确。听起来像是currentProducts
发生了变异而不是更新。setProducts
看起来像什么?它是这样的:@action setProducts=(products)=>{This.set('products',products)}
。不确定这是否与任何wya相关,但setProducts
所在的模型类用于其内部数据对象。@Oblosys请看下面我的答案。看来问题不在currentProducts
上。但事实上,这并不能回答我最初的问题。我恐怕无法进一步帮助您,因为我觉得当currentProducts
被修改而不是变异时,上面的代码应该可以工作。您可以尝试将函数作为第一个参数传递给withPropsOnChange
,以研究属性的确切变化。
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)