React使用Context开发购物车时如何正确更新对象数组类型的state?
React Context购物车对象数组状态更新方案
原有代码问题说明
- 直接修改state内的数组、对象属性不符合React状态更新规则,修改不会触发组件重渲染,还会导致状态异常
- 使用
JSON.stringify+includes判断商品是否存在的方式性能差,且容易出现误匹配(比如itemId值刚好是其他商品属性值的子字符串时会判定错误)
修正后的完整代码
import { createContext, Component } from 'react'; export const CartContext = createContext() class CartContextProvider extends Component { state = { productsToPurchase: [] } addProduct = (itemId) => { // 采用setState函数式更新写法,获取上一次的状态快照,避免异步更新的取值错误 this.setState(prevState => { // 查找是否已存在对应id的商品 const existingProductIdx = prevState.productsToPurchase.findIndex(product => product.itemId === itemId) if (existingProductIdx > -1) { // 拷贝原数组,不直接修改原state const updatedProducts = [...prevState.productsToPurchase] // 拷贝要修改的商品对象,更新数量 updatedProducts[existingProductIdx] = { ...updatedProducts[existingProductIdx], qty: updatedProducts[existingProductIdx].qty + 1 } return { productsToPurchase: updatedProducts } } else { // 新增商品时直接返回新拼接的数组 return { productsToPurchase: [...prevState.productsToPurchase, { itemId: itemId, qty: 1 }] } } }) } render() { return ( <CartContext.Provider value={{...this.state, addProduct: this.addProduct}}> {this.props.children} </CartContext.Provider> ) } } export default CartContextProvider;
核心修改点说明
- 所有状态更新都通过
setState完成,不直接修改this.state的属性值 - 数组、对象更新都基于浅拷贝生成新的引用,符合React不可变更新的要求
- 用
findIndex精准匹配商品id,判断逻辑更可靠
内容的提问来源于stack exchange,提问作者asem shaat
相关产品推荐
相关产品推荐

