为啥 setState() 在我的情况下不能在 React 中工作?
Posted
技术标签:
【中文标题】为啥 setState() 在我的情况下不能在 React 中工作?【英文标题】:Why setState() isn't working in React in my case?为什么 setState() 在我的情况下不能在 React 中工作? 【发布时间】:2021-12-27 23:55:53 【问题描述】:我正在尝试通过使用上下文来实现购物车。上下文工作正常,但我需要创建一种每次点击删除一个产品的方法。为此,我必须使用 useState()
函数。但是,它甚至不会改变状态中的数据。
这是我的函数代码。如果有什么不清楚的地方请告诉我
了解更多信息。 productsToPurchase
是一个包含所有已购买产品的数组,如下所示:
[itemId: "ps-5", qty:2,itemId: "iphone-xr", qty:4,itemId:"ps-4", qty:7]
export const CartContext = createContext()
class CartContextProvider extends Component
state =
productsToPurchase: [],
totalPrice:[]
addProduct = (itemId, prices) =>
this.setState(oldState =>
const objWithIdExist = oldState.productsToPurchase.find((o) => o.itemId === itemId);
return
productsToPurchase: !objWithIdExist
? [...oldState.productsToPurchase, itemId, qty: 1, price: prices ]
: oldState.productsToPurchase.map((o) =>
o.itemId !== itemId ? o : ...o, qty: o.qty + 1
)
)
this.setState(oldState=>
return
totalPrice: getTotalAmount(oldState.productsToPurchase)
)
decreaseProduct = (itemId) =>
this.setState(oldState=>
// catch the item by mapping
return oldState.productsToPurchase.map(product=>
if (product.itemId === itemId)
if (product.qty === 1)
//remove the product from the list
console.log("qty is 1!")
else
console.log("Quantity is more than 1")
return ...product, qty: product.qty - 1
)
)
render()
return (
<CartContext.Provider value=...this.state, addProduct: this.addProduct, decreaseProduct: this.decreaseProduct>
this.props.children
</CartContext.Provider>
)
function getTotalAmount(productsToPurchase)
const totalPrice = []
productsToPurchase.map((product, productIndex) =>
product.price.map((price, priceIndex)=>
if (productIndex === 0)
totalPrice.push(currency: price.currency, amount: price.amount * product.qty)
else
totalPrice.map(total=>
if (total.currency === price.currency)
total.amount = total.amount + (price.amount * product.qty)
)
)
)
return totalPrice
export default CartContextProvider;
【问题讨论】:
您需要在setState()
回调中返回新状态。见reactjs.org/docs/hooks-reference.html#functional-updates
您的回调 (oldState => ...
) 没有返回任何内容,因此永远不会写入新状态
这是map
回调中的返回,而不是setState
回调。您似乎还使用map
代替for..of
或forEach
,这不是它的用途(为什么开发人员继续这样做?)
@asemshaat 您没有返回新状态。应该是return oldState.productsToPurchase.map(...
。您传递给setState
的函数需要返回新状态。您正在谈论的返回是嵌套在 inside 的 map 函数。此外,如果您想从列表中删除产品,您也需要使用.filter
,或者.reduce
可用于在一次迭代中进行映射和过滤
提供者是一个类组件,而其他一切都是钩子和功能组件,这似乎很奇怪。我会让一切都发挥作用。
【参考方案1】:
如果您想从所选产品数量中减去 1,如果达到 0 则将其删除,试试这个
// Make sure you return the new state object in its entirety
this.setState(( productsToPurchase, ...oldState ) => (
...oldState,
productsToPurchase: productsToPurchase.reduce((arr, product) =>
// is this the selected product?
if (product.itemId === itemId)
// product qty > 1, include it with decrement
if (product.qty > 1)
return [...arr,
...product,
qty: product.qty - 1
]
return arr // otherwise exclude this product
// otherwise, just include this product
return [...arr, product]
, [])
))
【讨论】:
这行代码好像太多了。就我而言,我刚刚发现我必须在oldState.productsToPurchase.map(product=>
之前添加return
。我应该在return productsToPurchase: ...product, qty: product.qty - 1
做些什么
我真的不明白你的意思。仅供参考,没有 cmets 和间距,与原来的 13 行相比,它是 12 行,甚至没有从阵列中删除产品
qty = 0
时我还没有删除产品。当qty>0
在else
部分中时,我正在努力删除产品
第15行。如果从第一行算起
@asemshaat 我已改为使用较少行的 reduce。 IMO 它不那么可读,但这是主观的以上是关于为啥 setState() 在我的情况下不能在 React 中工作?的主要内容,如果未能解决你的问题,请参考以下文章