获取所选项目及其计数 [英] Get selected item and its count
问题描述
我正在尝试制作像
请帮助我在导航到购物车(袋子)页面时实现显示所选产品及其各自数量的结果.我为此苦苦挣扎了很长时间.所以我谦虚地请求您帮助我找到正确的解决方案.. 提前非常感谢..
问题
- 您有多个
AppProvider
组件,每个组件都为其封装的子组件提供不同的上下文. - 初始
AppContext
形状与 实际 作为上下文值传递的形状不匹配. cartItems
状态未作为数组维护.- 其他各种问题和模式
解决方案
删除所有无关的
AppProvider
提供程序组件,只使用一个将整个应用程序包装在_app.js
中.import { AppProvider } from "../components/context/AppContext";导出默认类 TailwindApp 扩展 App {使成为() {const { 组件,pageProps } = this.props;返回 (<应用程序提供者><组件 {...pageProps}/></AppProvider>);}}
修复上下文以具有与提供的值匹配的初始值.修复状态更新程序以正确管理
cartItems
数组.当cartItems
数组状态更新时,使用useEffect
挂钩计算派生的总项目计数状态.正确添加和更新项目/产品数量,当数量达到0时删除项目.import React, { useState, useEffect } from "react";导出 const AppContext = React.createContext({购物车:0,购物车项目:[],setCart: () =>{},addToCart: () =>{},removeFromCart: () =>{}});export const AppProvider = (props) =>{const [cart, setCart] = useState(0);常量 [cartItems, setCartItems] = useState([]);使用效果(() => {setCart(cartItems.reduce((count, {数量}) => 数量 + 数量, 0));}, [cartItems]);const addToCart = (product) =>{setCartItems((项目) => {if (items.find(({ id }) => id === product.id)) {返回 items.map((item) =>item.id === product.id?{...物品,数量:item.quantity + 1}: 物品);} 别的 {返回 [...项目,{...产品,数量:1}];}});};const removeFromCart = (product) =>{setCartItems((项目) => {const foundItem = items.find(({ id }) => id === product.id);if (foundItem?.quantity > 1) {返回 items.map((item) =>item.id === product.id?{...物品,数量:item.quantity - 1}: 物品);} 别的 {return items.filter(({ id }) => id !== product.id);}});};返回 (<AppContext.Provider value={{ 购物车, addToCart, removeFromCart, cartItems }}>{props.children}</AppContext.Provider>);};
在
Products.js
中移除所有本地项目计数状态,数量可以从上下文中的状态访问.有条件地呈现添加项目"以及项目计数上的递增/递减按钮.从next/link"导入链接;从反应"中导入 { useContext };从./context/AppContext"导入{ AppContext};const Product = (props) =>{常量 { 产品 } = 道具;const contextData = useContext(AppContext);常量计数 =contextData.cartItems.find(({ id }) => id === product.id)?.quantity ??0;const addToCart = (product) =>() =>{contextData.addToCart(product);};const removeFromCart = (product) =>() =>{contextData.removeFromCart(product);};返回 (...{数数 ?(...{数数}...) : (...<span className="标签">添加</span>...)}</div></div>);};
在
Cart.js
中,您可以导入和使用上下文来渲染和显示购物车项目.import { useContext } from "react";从../components/context/AppContext"导入{ AppContext};常量购物车 = () =>{常量 { 购物车, cartItems } = useContext(AppContext);返回 (
<h1>购物车页面 </h1><h2>商品总数:{cart}</h2><p><ul>{cartItems.map(({ id, name, quantity }) => (<li key={id}>{名称}:{数量}</li>))}</ul></p></div>);};注意:请注意,
id
属性已添加到您的products
数组中的所有商品/产品中以进行匹配/识别它们是一项更容易的任务.演示
I am trying to make a shopping cart app like this site but using reactjs.
index.js: (Sending each product to product
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>
Also I have the ADD button UI switch code and that will look like,
Before clicking add button,
------------ | ADD +| ------------
After clicking add button,
----------------- | - {count} +| -----------------
Things are fine as of now and the respective count(s) on each product individually gets added in home page.
Also with the help of contextApi made an
AppContext
and updated the cart like,const addToCart = (product) => { if (+cart >= 0) { setCart(+cart + 1); setCartItems(product); } };
In nav.js, I am getting the updated count of the products but when I click on the bag menu (Which is a cart page) , I am unable to fetch the context.
Expected Result
While visiting the cart page (On click of the bag menu in header), the page would display the so far selected product (with name and description) along with their quantity respectively.
Current Result:
Unable to get the appcontext data and display the selected product along with the quantity.
Working Snippet:
Please kindly help me to achieve the result of displaying the selected product and its respective quantity while navigating to cart (bag) page.. I am struggling with this for long.. So I humbly request you to help me with right solution.. Big thanks in advance..
解决方案Issues
- You've multiple
AppProvider
components each providing a different context to their wrapped children. - The initial
AppContext
shape doesn't match what is actually passed as the context's value. - The
cartItems
state isn't maintained as an array. - Other various issues and patterns
Solution
Remove all the extraneous
AppProvider
provider components, use just one to wrap your entire app in_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> ); } }
Fix the context to have an initial value that matches the provided value. Fix the state updaters to correctly manage the
cartItems
array. Use anuseEffect
hook to compute the derived total item count state when thecartItems
array state updates. Correctly add and update item/product quantities, and remove item when quantity reaches 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> ); };
In
Products.js
remove all the local item count state, quantities can be accessed from state in the context. Conditionally render the "Add Item" and increment/decrement buttons on the item count.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> ); };
In
Cart.js
you can import and consume the context to render and display the cart items.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> ); };
Note: Please note that an
id
property was added to all items/products in yourproducts
array to make matching/identifying them a much easier task.Demo
这篇关于获取所选项目及其计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文- You've multiple