React跨组件传值问题:如何在Cart页面展示购物车商品?
购物车跨页面数据共享解决方案
问题根源
当前购物车数据cartProducts仅存储在Products组件的本地状态中,而Products和Cart是路由切换的独立组件,彼此状态完全隔离,因此Cart页面的CartItems组件无法获取到已添加的购物车数据。
解决方案:使用React Context实现全局状态管理
1. 创建CartContext文件
新建CartContext.jsx,封装购物车的状态和操作方法:
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.id === product.id); if (existingItem) { return prevItems.map(item => item.id === product.id ? {...item, quantity: item.quantity + 1} : item ); } return [...prevItems, {...product, quantity: 1}]; }); }; // 修改商品数量 const updateQuantity = (productId, change) => { setCartItems(prevItems => prevItems.map(item => { if (item.id === productId) { const newQuantity = item.quantity + change; return newQuantity > 0 ? {...item, quantity: newQuantity} : null; } return item; }).filter(item => item !== null) ); }; return ( <CartContext.Provider value={{ cartItems, addToCart, updateQuantity }}> {children} </CartContext.Provider> ); } export function useCart() { return useContext(CartContext); }
2. 在根组件中包裹CartProvider
修改Main.jsx,用CartProvider包裹整个路由组件:
import React from 'react' import ReactDOM from 'react-dom/client' import { createBrowserRouter, RouterProvider } from "react-router-dom"; import App from './App.jsx' import Cart from './Cart.jsx' import { Products } from './Products.jsx' import { CartProvider } from './CartContext.jsx'; const router = createBrowserRouter([ { path: "/", element: <App />, }, { path: "/App", element: <App />, }, { path: "/products", element: <Products />, }, { path: "/cart", element: <Cart />, }, ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <CartProvider> <RouterProvider router={router} /> </CartProvider> </React.StrictMode> );
3. 修改Products组件,使用全局状态
更新Products.jsx,移除本地购物车状态,改用全局Context:
import { useState, useEffect } from 'react' import './Products.css' import NavBar from './NavBar.jsx' import { useCart } from './CartContext.jsx'; function CartItems({ products, updateQuantity }) { if (!products || products.length === 0) { return ( <> <h2>Cart is Empty</h2> </> ) } else { return ( <div id="cartItemList"> {products.map(product => ( <div className="cartItem" key={product.id}> <img src={product.image} alt={product.title} /> <p>{product.title}</p> <p>{product.description}</p> <p>${product.price}</p> <div> <button onClick={() => updateQuantity(product.id, -1)}>-</button> <p>{product.quantity}</p> <button onClick={() => updateQuantity(product.id, 1)}>+</button> </div> </div> ))} </div> ) } } function Products() { const [data, setData] = useState([]); const { cartItems, addToCart } = useCart(); useEffect(() => { fetch('https://fakestoreapi.com/products?limit=4') .then(response => response.json()) .then((data) => setData(data)) .catch((error) => console.error(error)); }, []); return ( <> <NavBar /> <div id="productsContainer"> {data.map(product => ( <div className="productBoxes" key={product.id}> <img className="productImg" src={product.image} alt={product.title} /> <h1>{product.title}</h1> <p>{product.description}</p> <p>${product.price}</p> <button onClick={() => addToCart(product)} className="productCheck" id="productButton">Add to Cart</button> </div> ))} <CartItems products={cartItems} updateQuantity={useCart().updateQuantity} /> </div> </> ); } export { Products, CartItems };
4. 修改Cart组件,获取全局购物车数据
更新Cart.jsx,通过Context获取购物车数据:
import './Cart.css' import NavBar from './NavBar.jsx' import { CartItems } from './Products.jsx' import { useCart } from './CartContext.jsx'; function Cart() { const { cartItems, updateQuantity } = useCart(); return ( <> <NavBar /> <CartItems products={cartItems} updateQuantity={updateQuantity} /> </> ); } export default Cart;
额外优化说明
- 拆分
CartItems到独立文件(如CartItems.jsx)可进一步优化代码结构 - 已实现重复商品数量累加逻辑,避免购物车出现重复条目
- 修复了原代码中所有商品共享同一数量的问题,现在每个商品拥有独立数量
内容的提问来源于stack exchange,提问作者MortalChris
相关产品推荐
相关产品推荐

