通过 useContext 传递函数

时间:2021-04-29 11:32:06

标签: reactjs use-state use-context


我目前正在为 React Context 苦苦挣扎。我想传递允许在上下文中显示/隐藏购物车逻辑的函数,而不是在组件之间使用道具。 我不明白为什么当单击 HeaderCartButton 组件中的按钮时,它不会触发我上下文中的 **onClick={ctx.onShowCart}**,即使当我控制台记录 carCtx.state 它已正确更新,然后应该在 App.js 中添加组件
//App.js

import { useContext } from "react";

import Header from "./components/Layout/Header";
import Meals from "./components/Meals/Meals";
import Cart from "./components/Cart/Cart";
import CartProvider from "./store/CartProvider";
import CartContext from "./store/cart-context";

function App() {
  const ctx = useContext(CartContext);

  return (
    <CartProvider>
      {ctx.state && <Cart />}
      <Header />
      <main>
        <Meals />
      </main>
    </CartProvider>
  );
}

export default App;
//cart-context.js

import React from "react";

const CartContext = React.createContext({
  state: false,
  onShowCart: () => {},
  onHideCart: () => {},
  items: [],
  totalAmount: 0,
  addItem: (item) => {},
  removeItem: (id) => {},
});

export default CartContext;

//CartProvider.js 

import CartContext from "./cart-context";
import { useState } from "react";

const CartProvider = (props) => {
  const [cartIsShown, setCartIsShown] = useState(false);

  const showCartHandler = () => {
    setCartIsShown(true);
  };

  const hideCartHandler = () => {
    setCartIsShown(false);
  };

  const handleAddItem = (item) => {};

  const handleRemoveItem = (id) => {};

  const cartCtx = {
    state: cartIsShown,
    onShowCart: showCartHandler,
    onHideCart: hideCartHandler,
    items: [],
    totalAmount: 0,
    addItem: handleAddItem,
    removeItem: handleRemoveItem,
  };

  return (
    <CartContext.Provider value={cartCtx}>
      {props.children}
    </CartContext.Provider>
  );
};

export default CartProvider;
//Header.js

import { Fragment } from "react";

import HeaderCartButton from "./HeaderCartButton";
import mealsImage from "../../assets/meals.jpg";
import classes from "./Header.module.css";

const Header = (props) => {
  return (
    <Fragment>
      <header className={classes.header}>
        <h1>ReactMeals</h1>
        <HeaderCartButton />
      </header>
      <div className={classes["main-image"]}>
        <img src={mealsImage} alt="A table full of delicious food!" />
      </div>
    </Fragment>
  );
};

export default Header;
//HeaderCartButton.js

import CartIcon from "../Cart/CartIcon";
import { useContext } from "react";
import classes from "./HeaderCartButton.module.css";
import CartContext from "../../store/cart-context";

const HeaderCartButton = (props) => {
  const ctx = useContext(CartContext);
  const numberOfCartItems = ctx.items.reduce((accumulator, item) => {
    return accumulator + item.amount;
  }, 0);

  return (
    <button className={classes.button} onClick={ctx.onShowCart}>
      <span className={classes.icon}>
        <CartIcon />
      </span>
      <span>Your Cart</span>
      <span className={classes.badge}>{numberOfCartItems}</span>
    </button>
  );
};

export default HeaderCartButton;

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

如果您查看您的 App 组件,您会在提供程序之外使用 CartContext

function App() {
  const ctx = useContext(CartContext);

  return (
    <CartProvider>
      {ctx.state && <Cart />}
      <Header />
      <main>
        <Meals />
      </main>
    </CartProvider>
  );
}

您应该修改它,使其类似于以下内容,其中您在提供程序内部使用上下文。

const Main = () => {
  return <CartProvider><App /></CartProvider>
}

 function App() {
      const ctx = useContext(CartContext);
    
      return (
          <>
          {ctx.state && <Cart />}
          <Header />
          <main>
            <Meals />
          </main>
         </>
      );
    }