React中实现点击加入购物车按钮添加商品至购物车页面的方案
解决方案:实现点击「ADD TO CART」添加商品到购物车功能
核心思路是在组件间共享购物车状态,让Product组件能触发添加动作,Cart组件能动态渲染购物车内的商品。下面分两种场景给出实现方式:
1. 跨组件场景:用React Context管理状态(推荐)
如果Product和Cart组件不在直接父子层级,用Context可以避免层层传递props的麻烦。
第一步:创建购物车Context
新建CartContext.js文件:
import { createContext, useContext, useState } from 'react'; const CartContext = createContext(); export function CartProvider({ children }) { const [cartItems, setCartItems] = useState([]); // 添加商品到购物车,支持重复商品累加数量 const addToCart = (product) => { setCartItems(prevItems => { const existingItem = prevItems.find(item => item.title === product.title); if (existingItem) { return prevItems.map(item => item.title === product.title ? {...item, quantity: item.quantity + 1} : item ); } else { return [...prevItems, {...product, quantity: 1}]; } }); }; return ( <CartContext.Provider value={{ cartItems, addToCart }}> {children} </CartContext.Provider> ); } // 自定义Hook,简化组件调用Context的代码 export function useCart() { return useContext(CartContext); }
第二步:在根组件包裹CartProvider
比如在App.js中:
import { CartProvider } from './CartContext'; import { Product } from './Product'; import Cart from './Cart'; function App() { return ( <CartProvider> {/* 这里放你的路由或组件结构,比如商品页面和购物车页面 */} <Product image="商品图片地址" image2="商品细节图地址" title="商品标题" price="89,90 €" /> <Cart /> </CartProvider> ); } export default App;
第三步:修改Product组件,绑定添加事件
import './Product.css'; import { useCart } from './CartContext'; export function Product(props){ const { addToCart } = useCart(); const handleAddToCart = () => { // 传递当前商品的核心信息到购物车 addToCart({ image: props.image, title: props.title, price: props.price }); }; return ( <> <div className="product-container"> <div className="product-background"> <img className='product-image' src={props.image} alt={props.title}></img> <img className='product-image2' src={props.image2} alt={`${props.title} 细节图`}></img> </div> </div> <div className='description-container'> <div className="product-description"> <div className='product-title'>{props.title}</div> <div className='product-price'>{props.price}</div> <div className='product-button'> <button type="button" className="product-btn" onClick={handleAddToCart} > ADD TO CART </button> </div> </div> </div> </> ) }
第四步:修改Cart组件,动态渲染商品
import './Cart.css' import { Header } from './Header' import { Card } from './Catalog' import { useCart } from './CartContext' function Price() { const { cartItems } = useCart(); // 计算购物车总价 const calculateTotal = () => { return cartItems.reduce((total, item) => { // 处理价格格式,将"89,90 €"转为数字计算 const price = parseFloat(item.price.replace(',', '.').replace(' €', '')); return total + price * item.quantity; }, 0).toFixed(2).replace('.', ',') + ' €'; }; return ( <div className='price-cont'> <div className='price-cointainer'> <div className='total'>TOTAL</div> <div className='price'>{calculateTotal()}</div> <div className='checkout'>CHECKOUT</div> </div> </div> ) } export default function Cart(){ const { cartItems } = useCart(); return ( <> <Header /> <div className='cart-container'> <div className='item-container'> {/* 遍历购物车商品,动态渲染Card */} {cartItems.map((item, index) => ( <Card key={`${item.title}-${index}`} image={item.image} title={item.title} price={item.price} quantity={item.quantity} /> ))} </div> </div> <Price /> </> ); }
2. 简单场景:父子组件状态提升
如果Product和Cart有共同的父组件,直接通过状态提升传递数据即可:
父组件(如App.js):
import { useState } from 'react'; import { Product } from './Product'; import Cart from './Cart'; function App() { const [cartItems, setCartItems] = useState([]); const addToCart = (product) => { setCartItems(prev => [...prev, product]); }; return ( <> <Product image="商品图片地址" image2="商品细节图地址" title="商品标题" price="89,90 €" addToCart={addToCart} /> <Cart cartItems={cartItems} /> </> ); }
修改Product组件:
import './Product.css'; export function Product(props){ const handleAddToCart = () => { props.addToCart({ image: props.image, title: props.title, price: props.price }); }; return ( <> {/* 原有结构不变,仅修改按钮点击事件 */} <div className='product-button'> <button type="button" className="product-btn" onClick={handleAddToCart} > ADD TO CART </button> </div> </> ) }
修改Cart组件:
export default function Cart({ cartItems }){ return ( <> <Header /> <div className='cart-container'> <div className='item-container'> {cartItems.map((item, index) => ( <Card key={index} image={item.image} title={item.title} price={item.price} /> ))} </div> </div> <Price /> </> ); }
注:如果
Card组件需要显示商品数量,记得传递quantity属性并在组件内渲染。
内容的提问来源于stack exchange,提问作者ljaskolka
相关产品推荐
相关产品推荐

