javascript 如何使按钮上的onClick事件与react中为其他按钮定义的onClick事件的工作方式相同

taor4pac  于 2023-02-18  发布在  Java
关注(0)|答案(1)|浏览(184)

我刚开始学习react,遇到了这个问题,我有两个按钮(菜单项中的添加按钮和购物车中的添加按钮),每个按钮都在不同的组件中定义。我通过菜单项中的添加按钮的属性定义了功能和添加逻辑,当用户单击时,添加按钮会更新数量、cartCount并将项目详细信息和数量添加到购物车中。现在,当我单击购物车中的添加按钮时,我想要一个类似的功能,如它应该更新购物车数量,菜单项和购物车数量计数。我知道应该有一些方法,而不是重复整个逻辑了。我知道这是一个很长的一个。谢谢提前回答!!!
App.js

import react, { useState, useEffect } from "react";
import Header from "./components/Header";
import LandingPage from "./components/LandingPage";
import MenuItems from "./components/menuItems";
import Cart from "./components/Cart";
import ItemContext from "./store/item-context";

function App() {

    const [items, setItems] = useState([]);
    const [total, setTotal] = useState(0);
    useEffect(() => {
        setTotal(() => {
            return items.reduce((acc, eachItem) => {
                return eachItem.quantity + acc;
            }, 0)
        })
    }, [items])

    const [cartBool, setCartBool] = useState(false);
    function AddedItem(item) {

        const foundIndex = items.findIndex(eachItem => {
            return eachItem.title === item.title;
        })

        if (foundIndex !== -1) {
            setItems(prev => {
                prev[foundIndex].quantity = item.quantity;
                return [...prev];
            })
        }
        else {
            setItems(prev => {
                return [...prev, item]
            })
        }
    }
    function handleCartClick() {
        setCartBool(true);
    }

    function handleCloseClick() {
        setCartBool(false);
    }
    return (
        <react.Fragment>
            <ItemContext.Provider value={{
                items: items
            }}>
                {cartBool &&
                    <Cart onCloseClick={handleCloseClick} />}
            

            <div className="parent-container">
                <Header cartCount={total} onCartClick={handleCartClick} />
                <LandingPage />
                <MenuItems onAddItem={AddedItem} />
            </div>
            </ItemContext.Provider>
        </react.Fragment>
    );
}

export default App;

Menu-items.js

import react from "react";
import MenuItem from "./menuItem";
import MenuContent from "./menuContent";

function MenuItems(props) {

    function handleItems(item){
        props.onAddItem(item);
    }
    return (
        <div className="menu">
            {MenuContent.map(eachItem =>{
                return <MenuItem title={eachItem.title} description={eachItem.description} price={eachItem.price} key={eachItem.key} onAdd={handleItems}/>
            })}
        </div>
    );
}

export default MenuItems;

Menu-item.js

import react , { useState } from "react";

function MenuItem(props) {
    const [item, setItem] = useState({
        title: "",
        quantity: 0,
        price: ""
    });

    function handleClick(){

        setItem(prev =>{
            return {
                title: props.title,
                quantity: prev.quantity + 1,
                price: props.price
            }
        })  
    }

    function handleSubmit(event){
        event.preventDefault();
        props.onAdd(item);
    }
    return (
        <div className="menu-item">
            <div className="menu-content">
                <h3>{props.title}</h3>
                <p>{props.description}</p>
                <h4>{props.price}</h4>
            </div>
            <form onSubmit={handleSubmit} className="add-items">
                <label htmlFor="Amount">Amount</label>
                <input onChange={() => {}} type="number" name="Amount" value={item.quantity}/>
                <button onClick={handleClick}  type="submit" className="btn btn-lg">Add</button>
            </form>
        </div>
    );
}
export default MenuItem;`

现在,我希望在单击Cart组件内CartItem组件中的AddButton时创建menuItem组件中定义的此项。

7cwmlq89

7cwmlq891#

请参见以下示例,其中包含我所做更改的注解和说明。
听起来好像您希望购物车在MenuItem中单击Add时更新。

修复onClickonSubmit的使用

这是您的问题的一部分。在MenuItem中,您使用了一个表单,并且表单提交按钮上有onClick。由于您的按钮有type="submit",它将激发提交事件沿着onSubmit处理程序。我们可以在此处简单地使用onSubmit作为处理程序,并从按钮中删除onClick
我简化了MenuItem来更新和读取状态中的数量值,然后在添加项目时,我们只需传递项目(因为它已经有了最新的数量)。
你的逻辑基本上是存在的。我给每个产品一个id,以简化跟踪所有的支柱钻井与使用titlekey,因为它只是有点容易让我把我的头周围。希望变化和评论是有意义的。

示例/演示(点击查看)

https://codesandbox.io/s/update-cart-example-veic1h

import "./styles.css";

import React, { useState, createContext, useContext, useEffect } from "react";

const CartContext = createContext();

export default function App() {
  const [cartItems, setCartItems] = useState([]);
  const [totalQuantity, setTotalQuantity] = useState(0);
  const [totalCost, setTotalCost] = useState(0);

  useEffect(() => {
    setTotalQuantity(() => {
      return cartItems.reduce((acc, item) => {
        return item.quantity + acc;
      }, 0);
    });
    setTotalCost(() => {
      return cartItems.reduce((acc, item) => {
        return item.quantity * item.price + acc;
      }, 0);
    });
  }, [cartItems]);

  function addItemToCart(newItem) {
    const existingCartItem = cartItems.findIndex((item) => {
      return item.id === newItem.id;
    });

    setCartItems((prevItems) => {
      return existingCartItem !== -1
        ? prevItems.map((prevItem) =>
            prevItem.id === newItem.id
              ? {
                  ...prevItem,
                  quantity: prevItem.quantity + newItem.quantity
                }
              : prevItem
          )
        : [...prevItems, newItem];
    });

    // the above is similar to what you have below,
    // but good practice not to mutate state directly
    // in case of incrementing item already found in cart...

    // if (foundIndex !== -1) {
    //   setCartItems((prev) => {
    //     prev[foundIndex].quantity = item.quantity;
    //     return [...prev];
    //   });
    // } else {
    //   setCartItems((prev) => {
    //     return [...prev, item];
    //   });
    // }
  }

  return (
    <CartContext.Provider value={{ cartItems, totalQuantity, totalCost }}>
      <div className="parent-container">
        <MenuItems onAddItem={addItemToCart} />
        <Cart />
      </div>
    </CartContext.Provider>
  );
}

const menuItems = [
  { title: "item 1", description: "description 1", price: "10", id: "1" },
  { title: "item 2", description: "description 2", price: "20", id: "2" },
  { title: "item 3", description: "description 3", price: "30", id: "3" }
];

function MenuItems(props) {
  function handleItems(item) {
    props.onAddItem(item);
  }
  return (
    <div className="menu">
      {menuItems.map((item) => {
        return (
          <MenuItem
            title={item.title}
            description={item.description}
            price={item.price}
            key={item.id}
            // added this as prop
            id={item.id}
            onAdd={handleItems}
          />
        );
      })}
    </div>
  );
}

function MenuItem(props) {
  const [item, setItem] = useState({
    title: props.title,
    quantity: 0,
    price: props.price,
    // included a unique item id here
    id: props.id
  });

  // Don't need this anymore...
  // function handleClick(e) {
  //   ...
  // }

  // update quantity as we type by getting as state...
  function changeQuantity(e) {
    e.preventDefault();
    setItem((prev) => {
      return {
        ...prev,
        quantity: Number(e.target.value)
      };
    });
  }

  function handleSubmit(event) {
    event.preventDefault();
    props.onAdd(item);
  }
  return (
    <div className="menu-item">
      <div className="menu-content">
        <h3>{props.title}</h3>
        <p>{props.description}</p>
        <h4>Price: ${props.price}</h4>
      </div>
      <form onSubmit={handleSubmit} className="add-items">
        <label htmlFor="Amount">Amount</label>
        <input
          onChange={changeQuantity}
          type="number"
          name="Amount"
          value={item.quantity}
        />
        {/* No need for onClick on button, onSubmit already handles it */}
        <button type="submit" className="btn btn-lg">
          Add
        </button>
      </form>
    </div>
  );
}

function Cart() {
  const cart = useContext(CartContext);
  const { cartItems, totalQuantity, totalCost } = cart;
  return (
    <div>
      <h2>Cart</h2>
      <h3>Items:</h3>
      {cartItems.length > 0 &&
        cartItems.map(
          (item) =>
            item.quantity > 0 && (
              <div key={item.id}>
                {item.title} - quantity: {item.quantity}
              </div>
            )
        )}
      <h3>Total Items: {totalQuantity}</h3>
      <h3>Total Cost: {`$${totalCost.toFixed(2)}`}</h3>
    </div>
  );
}

相关问题