如何解决获取所选项目及其计数
我正在尝试制作一个类似于 this site 的购物车应用,但使用的是 reactjs。
index.js:(将每个产品发送到产品 component
)
{products.length > 0
? products.map((product) => (
<Product key={product.id} product={product} />
))
: ""}
components/product.js:
<div>
{product?.price}
<h3>
{product.name ? product.name : ""}
</h3>
<div dangerouslySetInnerHTML={{ __html: product?.description }} />
</div>
我还有添加按钮 UI 开关代码,看起来像,
在点击添加按钮之前,
------------
| ADD +|
------------
点击添加按钮后,
-----------------
| - {count} +|
-----------------
目前一切正常,每个产品的相应数量会单独添加到主页中。
也在 contextApi 的帮助下制作了一个 AppContext
并更新了购物车,
const addToCart = (product) => {
if (+cart >= 0) {
setCart(+cart + 1);
setCartItems(product);
}
};
在 nav.js 中,我获得了产品的更新数量,但是当我点击购物袋菜单(这是一个购物车页面)时,我无法获取上下文。
预期结果
在访问购物车页面时(点击标题中的购物袋菜单),页面将分别显示目前选择的产品(包括名称和描述)及其数量。
当前结果:
无法获取 appcontext 数据并显示所选产品和数量。
工作片段:
请帮助我在导航到购物车(袋)页面时实现显示所选产品及其各自数量的结果。 .. 提前致谢..
解决方法
问题
- 您有多个
AppProvider
组件,每个组件都为其包装的子级提供不同的上下文。 - 初始
AppContext
形状与实际作为上下文值传递的内容不匹配。 -
cartItems
状态不作为数组维护。 - 其他各种问题和模式
解决方案
-
删除所有无关的
AppProvider
提供程序组件,仅使用一个将整个应用程序包装在_app.js
中。import { AppProvider } from "../components/context/AppContext"; export default class TailwindApp extends App { render() { const { Component,pageProps } = this.props; return ( <AppProvider> <Component {...pageProps} /> </AppProvider> ); } }
-
修复上下文以获得与提供的值匹配的初始值。修复状态更新器以正确管理
cartItems
数组。当useEffect
数组状态更新时,使用cartItems
钩子计算派生的总项目计数状态。正确添加和更新商品/产品数量,并在数量达到 0 时移除商品。import React,{ useState,useEffect } from "react"; export const AppContext = React.createContext({ cart: 0,cartItems: [],setCart: () => {},addToCart: () => {},removeFromCart: () => {} }); export const AppProvider = (props) => { const [cart,setCart] = useState(0); const [cartItems,setCartItems] = useState([]); useEffect(() => { setCart(cartItems.reduce((count,{ quantity }) => count + quantity,0)); },[cartItems]); const addToCart = (product) => { setCartItems((items) => { if (items.find(({ id }) => id === product.id)) { return items.map((item) => item.id === product.id ? { ...item,quantity: item.quantity + 1 } : item ); } else { return [ ...items,{ ...product,quantity: 1 } ]; } }); }; const removeFromCart = (product) => { setCartItems((items) => { const foundItem = items.find(({ id }) => id === product.id); if (foundItem?.quantity > 1) { return items.map((item) => item.id === product.id ? { ...item,quantity: item.quantity - 1 } : item ); } else { return items.filter(({ id }) => id !== product.id); } }); }; return ( <AppContext.Provider value={{ cart,addToCart,removeFromCart,cartItems }}> {props.children} </AppContext.Provider> ); };
-
在
Products.js
中删除所有本地项目计数状态,可以从上下文中的状态访问数量。在项目计数上有条件地呈现“添加项目”和递增/递减按钮。import Link from "next/link"; import { useContext } from "react"; import { AppContext } from "./context/AppContext"; const Product = (props) => { const { product } = props; const contextData = useContext(AppContext); const count = contextData.cartItems.find(({ id }) => id === product.id)?.quantity ?? 0; const addToCart = (product) => () => { contextData.addToCart(product); }; const removeFromCart = (product) => () => { contextData.removeFromCart(product); }; return ( ... {count ? ( ... {count} ... ) : ( ... <span className="label">ADD</span> ... )} </div> </div> ); };
-
在
Cart.js
中,您可以导入和使用上下文来呈现和显示购物车项目。import { useContext } from "react"; import { AppContext } from "../components/context/AppContext"; const Cart = () => { const { cart,cartItems } = useContext(AppContext); return ( <div> <h1> Cart Page </h1> <h2>Total Item Count: {cart}</h2> <p> <ul> {cartItems.map(({ id,name,quantity }) => ( <li key={id}> {name}: {quantity} </li> ))} </ul> </p> </div> ); };
注意:请注意,id
属性已添加到您的 products
数组中的所有项目/产品中,以使匹配/识别它们变得更加容易.
演示
,您需要将 AppProvider
移至 _app.js
并将其从 index.js
和 cart.js
中删除,然后两个页面才能访问相同的上下文。
您的 _app.js
应如下所示
import React from "react";
import App from "next/app";
import { AppProvider } from "../components/context/AppContext";
export default class TailwindApp extends App {
render() {
const { Component,pageProps } = this.props;
return (
<AppProvider>
<Component {...pageProps} />
</AppProvider>
);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。