首页 > 解决方案 > 获取所选项目及其计数

问题描述

我正在尝试制作一个像这个网站一样的购物车应用程序,但使用reactjs

index.js:(将每个产品发送到 product component

        {products.length > 0
          ? products.map((product) => (
              <Product key={product.id} product={product} />
            ))
          : ""}

组件/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 数据并显示所选产品以及数量。

工作片段:

使用带有 Next.js 的 Tailwind 进行编辑(分叉)

请帮助我实现在导航到购物车(袋)页面时显示所选产品及其各自数量的结果。我为此苦苦挣扎了很长时间。所以我谦虚地请求您帮助我解决正确的问题。大提前致谢..

标签: javascriptreactjsnext.jscartshopping-cart

解决方案


问题

  1. 您有多个AppProvider组件,每个组件都为其包装的子组件提供不同的上下文。
  2. 初始形状与实际作为上下文值传递的AppContext形状不匹配。
  3. 状态不作为cartItems数组维护。
  4. 其他各种问题和模式

解决方案

  1. 删除所有无关的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>
        );
      }
    }
    
  2. 修复上下文以具有与提供的值匹配的初始值。修复状态更新程序以正确管理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>
      );
    };
    
  3. 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>
      );
    };
    
  4. 您可以在其中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数组中的所有项目/产品中,以使匹配/识别它们变得更加容易。

演示

使用带有 Next.js 的 Tailwind 进行编辑(分叉)


推荐阅读