MERN栈购物车子组件数量变更后,如何同步更新父组件总价?
问题:购物车子组件修改数量后父组件总价未同步更新
购物车父组件包含CartItem子组件,子组件配备商品数量增减按钮。修改数量时,子组件状态与数据库已完成更新,但父容器展示的购物车总价未同步更新。
父组件代码
const Cart = () => { const [cartItems, setCartItems] = useState([]); const[Total,setTotal] = useState(0) const userID = useGetUserID() useEffect(() => { fetchCartitems(); }, []); const fetchCartitems = async () => { try { const response = await axios.get( `http://localhost:5174/cart/getcart/${userID}` ); setCartItems(response.data.cartItems); } catch (err) { console.log(err); } }; useEffect(() => { setTotal(cartItems.reduce((total, item) => { return total + item.price * item.quantity; },0)); }, [cartItems]); console.log(Total) return ( <div className='container px-10 flex'> <div> <h2 className='py-6'>My Cart</h2> <ul className='space-y-3'> {cartItems.map(item => ( <CartItem key={item.productId} productId={item.productId} title={item.name} price={item.price} quantity={item.quantity} imgs={item.imgs}/> ))} </ul> </div> <div> {Total} </div> </div> ); } export default Cart
子组件代码
const CartItem = (props) => { const [qty, setqty] = useState(props.quantity) const decreaseQuantity = async (productId, quantity) => { try { const response = await axios.patch("http://localhost:5174/cart/updatecart", { productId, quantity: qty - 1, userID: useGetUserID(), }); if(qty > 1){ setqty(qty => qty - 1) } console.log(response.data); } catch (err) { console.error(err.response.data); } } const increaseQuantity = async (productId, quantity) => { try { const response = await axios.patch("http://localhost:5174/cart/updatecart", { productId, quantity: qty + 1, userID: useGetUserID(), }); if(qty >= 1){ setqty(qty => qty + 1) } console.log(response.data); } catch (err) { console.error(err.response.data); } } return ( <div className='flex space-x-3 font-Inter'> <div> <img src={props.imgs} alt="" className='w-32 h-32 rounded-md'/> </div> <div className="flex flex-col justify-between"> <h1 className='font-bold text-xl'>{props.title}</h1> <h1>{props.price}</h1> <div className="flex"> <button className='border border-b-2 px-3 rounded-tl-md rounded-bl-md' onClick={() =>decreaseQuantity(props.productId,props.quantity)}>-</button> <h1 className='px-2'>{qty}</h1> <button className='border border-b-2 px-3 rounded-tr-md rounded-br-md' onClick={() =>increaseQuantity(props.productId,props.quantity)}>+</button> </div> </div> </div> ) } export default CartItem
原因分析
父组件的cartItems状态仅在组件挂载时通过fetchCartitems获取一次。子组件修改数量后,父组件的cartItems未更新,导致依赖cartItems计算总价的useEffect不会触发,总价自然无法同步。
解决方案
方案一:子组件修改后通知父组件刷新数据
让子组件在完成数据库更新后,调用父组件传递的刷新函数,重新获取购物车数据:
- 父组件新增刷新函数并传递给子组件
const Cart = () => { // ... 原有代码不变 // 添加刷新购物车的函数 const refreshCart = () => { fetchCartitems(); }; return ( <div className='container px-10 flex'> <div> <h2 className='py-6'>My Cart</h2> <ul className='space-y-3'> {cartItems.map(item => ( <CartItem // ... 原有props不变 refreshCart={refreshCart} // 传递刷新函数 /> ))} </ul> </div> <div>{Total}</div> </div> ); };
- 子组件接收并调用刷新函数
const CartItem = (props) => { const [qty, setqty] = useState(props.quantity) const decreaseQuantity = async (productId) => { try { if (qty <= 1) return; // 提前拦截无效操作 const response = await axios.patch("http://localhost:5174/cart/updatecart", { productId, quantity: qty - 1, userID: useGetUserID(), }); setqty(prev => prev - 1); props.refreshCart(); // 调用父组件刷新函数 console.log(response.data); } catch (err) { console.error(err.response.data); } } const increaseQuantity = async (productId) => { try { const response = await axios.patch("http://localhost:5174/cart/updatecart", { productId, quantity: qty + 1, userID: useGetUserID(), }); setqty(prev => prev + 1); props.refreshCart(); // 调用父组件刷新函数 console.log(response.data); } catch (err) { console.error(err.response.data); } } // ... 原有return内容不变 };
方案二:父组件统一管理状态(更推荐)
让父组件负责所有购物车数据的状态管理,子组件仅触发操作,避免状态分散导致的不同步:
- 父组件新增数量修改函数并传递给子组件
const Cart = () => { // ... 原有代码不变 // 修改商品数量的函数 const updateQuantity = async (productId, newQty) => { try { if (newQty < 1) return; // 先更新本地状态,提升用户体验 setCartItems(prev => prev.map(item => item.productId === productId ? {...item, quantity: newQty} : item )); // 再同步更新数据库 await axios.patch("http://localhost:5174/cart/updatecart", { productId, quantity: newQty, userID, }); } catch (err) { console.error(err.response.data); // API失败时回滚状态 fetchCartitems(); } }; return ( <div className='container px-10 flex'> <div> <h2 className='py-6'>My Cart</h2> <ul className='space-y-3'> {cartItems.map(item => ( <CartItem // ... 原有props不变 updateQuantity={updateQuantity} // 传递修改函数 /> ))} </ul> </div> <div>{Total}</div> </div> ); };
- 子组件移除本地状态,直接使用父组件传递的数据
const CartItem = (props) => { const decreaseQuantity = () => { props.updateQuantity(props.productId, props.quantity - 1); }; const increaseQuantity = () => { props.updateQuantity(props.productId, props.quantity + 1); }; return ( <div className='flex space-x-3 font-Inter'> <div> <img src={props.imgs} alt="" className='w-32 h-32 rounded-md'/> </div> <div className="flex flex-col justify-between"> <h1 className='font-bold text-xl'>{props.title}</h1> <h1>{props.price}</h1> <div className="flex"> <button className='border border-b-2 px-3 rounded-tl-md rounded-bl-md' onClick={decreaseQuantity}>-</button> <h1 className='px-2'>{props.quantity}</h1> <button className='border border-b-2 px-3 rounded-tr-md rounded-br-md' onClick={increaseQuantity}>+</button> </div> </div> </div> ) };
内容的提问来源于stack exchange,提问作者Diego Sanchez
相关产品推荐
相关产品推荐

