我正在编写这个产品列表组件,并且我正在与州政府作斗争。列表中的每个产品本身都是一个组件。除了组件在道具更改时不会更新之外,所有内容都是按照假设进行渲染的。我正在使用recompose的withPropsOnChange(),希望每次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函数返回一个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。我想这是可行的。但在开始之前,我想知道我在这里做错了什么。
发布于 2018-05-18 20:46:18
正如我想象的那样,使用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)这里的变化是:
addedToCart;addedToCart "calculation";withState,以便在产品成功添加到购物车时调用addToCart处理程序中的setAddedToCart(true);componentWillReceiveProps事件,以便在道具更改时更新addedToCart。其中一些更新是基于this answer的。
发布于 2020-01-16 00:01:34
我认为您面临的问题是由于withPropsOnChange的返回值造成的。你只需要做:
withPropsOnChange([
'product',
'currentProducts',
], ({
product,
currentProducts,
}) => ({
addedToCart: currentProducts.indexOf(product.id) !== -1,
})
)和withProps一样,withPropsOnChange会自动将你返回的对象合并成道具。不需要Object.assign()。
参考:https://github.com/acdlite/recompose/blob/master/docs/API.md#withpropsonchange
附言:如果可以的话,我也会将条件替换为currentProducts.includes(product.id)。它更明确。
https://stackoverflow.com/questions/50409954
复制相似问题