React-Redux购物车组件:实现单商品数量增减与删除的问题
问题分析
你当前的核心问题是用了全局的quantity状态变量,所有商品共享这个值,所以修改时会同步改变所有商品的数量。另外,Redux全局状态不能通过组件本地状态修改,必须通过dispatch对应的action来更新购物车数据。
解决方案
第一步:配置Redux的Cart Reducer和Action
首先需要在Redux中定义处理商品数量增减、删除的action和reducer,确保能定位到具体商品进行修改:
// cartReducer.js const initialState = { products: [], total: 0 }; const cartReducer = (state = initialState, action) => { switch (action.type) { case "INCREASE_QUANTITY": return { ...state, products: state.products.map(item => item.id === action.payload.id ? {...item, quantity: item.quantity + 1} : item ), total: state.total + action.payload.price }; case "DECREASE_QUANTITY": const targetItem = state.products.find(item => item.id === action.payload.id); return { ...state, products: state.products.map(item => item.id === action.payload.id ? {...item, quantity: item.quantity > 1 ? item.quantity - 1 : 1} : item ), total: state.total - (targetItem.quantity > 1 ? action.payload.price : 0) }; case "DELETE_PRODUCT": const deletedProduct = state.products.find(item => item.id === action.payload.id); return { ...state, products: state.products.filter(item => item.id !== action.payload.id), total: state.total - (deletedProduct.price * deletedProduct.quantity) }; default: return state; } }; export default cartReducer;
// cartActions.js export const increaseQuantity = (product) => ({ type: "INCREASE_QUANTITY", payload: product }); export const decreaseQuantity = (product) => ({ type: "DECREASE_QUANTITY", payload: product }); export const deleteProduct = (product) => ({ type: "DELETE_PRODUCT", payload: product });
第二步:修改Cart组件代码
移除本地状态,通过dispatch触发Redux action来单独操作每个商品:
import RemoveIcon from '@mui/icons-material/Remove'; import AddIcon from '@mui/icons-material/Add'; import { useSelector, useDispatch } from "react-redux"; import styled from "styled-components"; import { useEffect } from "react"; import { userRequest } from "../requestMethods"; import { useHistory } from "react-router"; import React from "react"; import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined'; // 导入Redux action import { increaseQuantity, decreaseQuantity, deleteProduct } from "../cartActions"; const Cart = () => { const cart = useSelector((state) => state.cart); const history = useHistory(); const dispatch = useDispatch(); useEffect(() => { const makeRequest = async () => { try { const res = await userRequest.post("/checkout/payment", { amount: cart.total * 100, }); history.push("/success", { products: cart, }); } catch (err) { console.error(err); // 添加错误日志 } }; // 建议将支付逻辑改为按钮触发,而非自动执行 cart.total >= 1 && makeRequest(); }, [cart.total, history]); // 单独增加指定商品数量 const handleIncrease = (product) => { dispatch(increaseQuantity(product)); }; // 单独减少指定商品数量(最低为1) const handleDecrease = (product) => { if (product.quantity > 1) { dispatch(decreaseQuantity(product)); } }; // 单独删除指定商品 const handleDelete = (product) => { dispatch(deleteProduct(product)); }; return ( <div> {/* 补充根容器,符合React组件要求 */} {cart.products.map((product) => ( <Product key={product.id}> {/* 循环必须添加唯一key */} <PriceDetail> <ProductAmountContainer> <AddIcon onClick={() => handleIncrease(product)} /> <ProductAmount>{product.quantity}</ProductAmount> <RemoveIcon onClick={() => handleDecrease(product)} /> <DeleteOutlineOutlinedIcon style={{ marginLeft: "10px" }} onClick={() => handleDelete(product)} /> </ProductAmountContainer> <ProductPrice> $ {product.price * product.quantity} </ProductPrice> </PriceDetail> </Product> ))} </div> ); }; export default Cart;
关键修改点
- 移除组件内的
quantity和product本地状态,完全依赖Redux全局购物车数据 - 每个操作函数接收当前商品作为参数,通过
dispatch触发对应action,精准定位要修改的商品 - 列表循环添加
key={product.id},符合React渲染规范 - 修复了原组件return语句缺少根容器的问题
内容的提问来源于stack exchange,提问作者Wladyka
相关产品推荐
相关产品推荐

