我正在尝试创建一个购物车页面。我有一个产品文件,它从 fakestoreapi 获取产品,映射它们并显示它。还有一个按钮,onClick 将产品(从获取的数据中检索到的单个产品对象)传递到另一个组件 (CarItems) 并创建包含购物车项目的 div。
我的问题是我似乎只能在产品文件页面上显示它,而不是我想要的购物车文件。
我尝试将 CartItems 组件分离到另一个文件,但这似乎阻止了任何变量传递给它。尝试使用教程中的 propTypes 但这也没有帮助。任何解决方案都只允许我在我的产品页面文件中显示购物车的商品。
产品.jsx
import { useState } from 'react'
import { useEffect } from 'react'
import './Products.css'
import NavBar from './NavBar.jsx'
function CartItems({ products }) {
const [quantity, setQuantity] = useState(0);
function add() {
setQuantity(quantity + 1);
}
function subtract() {
if (quantity > 0) {
setQuantity(quantity - 1);
}
}
if (products && products.length === 0) {
console.log("Empty Cart")
return (
<>
<h2>Cart is Empty</h2>
</>
)
} else {
console.log("Car has items")
return (
<div id="cartItemList">
{products && 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={subtract}>-</button>
<p>{quantity}</p>
<button onClick={add}>+</button>
</div>
</div>
))}
</div>
)
}
}
function Products() {
const [data, setData] = useState([]);
const [cartProducts, setCartProducts] = useState([]);
useEffect(() => {
fetch('https://fakestoreapi.com/products?limit=4')
.then(response => response.json())
.then((data) => setData(data))
.catch((error) => console.error(error));
}, []);
function addToCart(product) {
setCartProducts(prevCart => [...prevCart, product]);
}
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={cartProducts} />
</div>
</>
);
}
export { Products, CartItems };
购物车.jsx
// import { useState } from 'react'
import './Cart.css'
import NavBar from './NavBar.jsx'
import { CartItems } from './Products.jsx'
function Cart() {
return (
<>
<NavBar />
<CartItems />
</>
);
}
export default Cart;
应用程序.jsx
import NavBar from './NavBar.jsx'
import './App.css'
function App() {
return (
<>
<NavBar />
<div id="hero">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente, ullam quaerat. Dolores labore aspernatur eos, molestiae hic laboriosam, magni nostrum vel aut mollitia voluptatum ducimus nesciunt minima, voluptas ea explicabo.</p>
<a href="products"><button>Products</button></a>
</div>
<footer>
<p>Made by Christian A. Valeri</p>
</footer>
</>
)
}
export default App;
Main.jsx
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 {CartItems, Products} from './Products.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>
<RouterProvider router={router} />
</React.StrictMode>
);
现在,我想到的只有两种方法来实现你想要的。第一个是使用react-router-dom提供的useParams钩子,第二个是使用任何状态管理库,例如redux或React的内置Context API以及useState或useReducer。
我选择了 Context API + useState hook,因为它更容易让你理解,而且它的可扩展性非常好。解决办法如下:
main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import App from "./App";
import Cart from "./components/Cart";
import Products from "./components/Products";
import ProductContextProvider from "./context/ProductContext";
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>
<ProductContextProvider>
<RouterProvider router={router} />
</ProductContextProvider>
</React.StrictMode>
);
应用程序.jsx
import { Link } from "react-router-dom";
function App() {
return (
<>
<div id="hero">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente,
ullam quaerat. Dolores labore aspernatur eos, molestiae hic
laboriosam, magni nostrum vel aut mollitia voluptatum ducimus nesciunt
minima, voluptas ea explicabo.
</p>
<Link to="/products">
<button>Products</button>
</Link>
</div>
<footer>
<p>Made by Christian A. Valeri</p>
</footer>
</>
);
}
export default App;
以下文件位于名为“components”的文件夹中:
购物车.jsx
import { useProductContext } from "../context/ProductContext";
import CartItems from "./CartItems";
function Cart() {
const { cartProducts } = useProductContext();
return <CartItems products={cartProducts} />;
}
export default Cart;
CartItems.jsx
import { useState } from "react";
function CartItems({ products }) {
const [quantity, setQuantity] = useState(0);
function add() {
setQuantity(quantity + 1);
}
function subtract() {
if (quantity > 0) {
setQuantity(quantity - 1);
}
}
if (products && products.length === 0) {
console.log("Empty Cart");
return (
<>
<h2>Cart is Empty</h2>
</>
);
} else {
console.log("Cart has items");
return (
<div id="cartItemList">
{products &&
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={subtract}>-</button>
<p>{quantity}</p>
<button onClick={add}>+</button>
</div>
</div>
))}
</div>
);
}
}
export default CartItems;
产品.jsx
import { useState } from "react";
import { useEffect } from "react";
import { useProductContext } from "../context/ProductContext";
import { Link } from "react-router-dom";
function Products() {
const [data, setData] = useState([]);
const { addToCart } = useProductContext();
useEffect(() => {
fetch("https://fakestoreapi.com/products?limit=4")
.then((response) => response.json())
.then((data) => setData(data))
.catch((error) => console.error(error));
}, []);
return (
<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);
alert("Product added to cart");
}}
className="productCheck"
id="productButton"
>
Add to Cart
</button>
</div>
))}
<br />
<br />
<br />
<br />
<br />
<Link to="/cart">
<button>Checkout</button>
</Link>
</div>
);
}
export default Products;
下面的文件存储在名为“context”的文件夹中:
ProductContext.jsx
import { createContext, useContext, useState } from "react";
const ProductContext = createContext([]);
function ProductContextProvider({ children }) {
const [cartProducts, setCartProducts] = useState([]);
const addToCart = (product) => {
setCartProducts((prevCart) => [...prevCart, product]);
};
return (
<ProductContext.Provider value={{ cartProducts, addToCart }}>
{children}
</ProductContext.Provider>
);
}
export default ProductContextProvider;
function useProductContext() {
return useContext(ProductContext);
}
export { useProductContext };
尝试一下,如果您有任何其他问题,请回复我
#react #context #react-hooks #javascript