React中使用Redux管理状态时map渲染的列表项状态互相影响是什么原因?
问题原因
- 你当前的Redux状态里只维护了单个全局的
productQuantity数值,所有列表项的价格计算都共用这同一个值,只要这个值变动,所有商品的计算价格都会同步变化 - 触发数量修改的
setProductQuantityaction没有携带「要修改的商品唯一标识」参数,不管修改哪个商品的输入,都是修改同一个全局数量值 - 额外问题:你当前的列表渲染没有给每个
product-in-cart节点加唯一key属性,容易引发其他渲染异常
修复方案
第一步:调整Redux状态结构
不要单独维护全局的productQuantity,给productsInCart数组里的每个商品对象新增quantity字段存储对应商品的数量,初始值设为1即可。
第二步:修改action逻辑
调整setProductQuantity的入参,需要同时接收「商品唯一ID」和「新数量」两个参数,reducer里根据ID找到对应商品修改它的quantity字段,示例reducer逻辑:
// 对应reducer逻辑示例 const cartSlice = createSlice({ name: 'cart', initialState: { productsInCart: [] }, reducers: { setProductQuantity: (state, action) => { const { productId, quantity } = action.payload const targetProduct = state.productsInCart.find(item => item.id === productId) if (targetProduct) { targetProduct.quantity = Number(quantity) } } } })
第三步:调整业务代码
// 调整事件处理函数,接收商品ID参数 const handleProductQuantity = (productId, event) => { dispatch(setProductQuantity({ productId, quantity: event.target.value })); } // 渲染部分调整 <div className='cart'> <div className='products-in-cart-wrapper'> { productsInCart ? ( productsInCart.map(productInCart => ( // 加唯一key <div className='product-in-cart' key={productInCart.id}> <div className="product-in-cart-name"> <div className="label label-title"> Title: </div> <div className="value value-title"> {productInCart.title} </div> </div> <div className="product-in-cart-price"> <div className="label label-price"> Price: </div> <div className="value value-price"> {/* 用当前商品自己的quantity计算 */} {productInCart.quantity * productInCart.price} </div> </div> <div className="product-in-cart-price"> <div className="label label-price"> Quantity: </div> <div className="value value-quantity"> {/* 传入当前商品ID,同时绑定value */} <input onChange={(e) => handleProductQuantity(productInCart.id, e)} type="number" value={productInCart.quantity} placeholder='1' /> </div> </div> <div className="button-cont"> <button className="buy-button" onClick={test}> Buy now </button> </div> </div> )) ) : ( <div> Loading... </div> ) } <div className="total-price-button-cont"> <button>Buy all for: 100$</button> </div> </div> </div>
内容的提问来源于stack exchange,提问作者Jubo Mdivnishvili
相关产品推荐
相关产品推荐

