0

I'm building a pretty simple restaurant website using React and Next.js. I have a home page and an 'order' page, which renders a menu from a state object ('menuitems'). I want the user to be able to add items to their 'cart', which is another state object. So ultimately I'm transferring data from the static 'menuitems' state to the 'cart.'

What I can't figure out is how I can update the 'cart' state from my 'order' page.

I've set up a context for the app going off of this guide. I've been able to successfully access the menu using a call to the custom hook 'useAppContext()' but I no longer have access to the updater functions provided through useState() or useContext() calls I previously used when I built something similar with everything in a single file (you can see in my code below where I invoke the now-undefined setCartItem() function).

How can I update the 'cartitems' state from inside of my 'order' component?

File where I have my context object:


import { createContext, useContext } from "react";

const AppContext = createContext();

export function AppWrapper({ children }) {
  const state = {
    menuitems: [
      {
        title: "Spagett",
        description: "Our finest spagett made with homemade meatballs and sauce.",
      },
      {
        title: "Sandwich",
        description: "You gotta try this sandwich",
      },
      {
        title: "BFB",
        description: "Watch out for your toilet after this one bro",
      },
    ],
    cartitems: []

  }



  return (
    <AppContext.Provider
      value={state}
    >
      {children}
    </AppContext.Provider>
  );
}

export function useAppContext() {
  return useContext(AppContext);
}

My _app.js file:

import "../styles/globals.css";
import { AppWrapper } from "./context/state";

function MyApp({ Component, pageProps }) {
  return (
    <AppWrapper>
      <Component {...pageProps} />
    </AppWrapper>
  );
}

export default MyApp;

Finally, my 'order' component, where I am trying to update the 'cartitems' state:

import Link from "next/link";
import { useAppContext } from "./context/state";


//IMPORT CONTEXT

const OrderPage = () => {
  const { menuitems } = useAppContext();
  const { cartitems } = useAppContext();


  const renderedMenu = menuitems.map((item) => (
    <div key={item.name} className="order-item">
      <h4>{item.title}</h4>
      <p>{item.description}</p>
      <button onClick={() => setCartItem([...cartitems, item.title])}>
        Add Item
      </button>
    </div>
  ));

  return (
    <div>

      <Link href="/">
        <a>Go home</a>

      </Link>
      <div>{renderedMenu}</div>
    </div>
  );
};

export default OrderPage;

1 Answers1

0

Create a state in your provider, then pass setCartItems into your context.

export function AppWrapper({ children }) {

  const [ cartItems, setCardItems ] = useState([])
  const state = {
    menuitems: [
      {
        title: "Spagett",
        description: "Our finest spagett made with homemade meatballs and sauce.",
      },
      {
        title: "Sandwich",
        description: "You gotta try this sandwich",
      },
      {
        title: "BFB",
        description: "Watch out for your toilet after this one bro",
      },
    ],
    cartitems: []

  }



  return (
    <AppContext.Provider
      value={{ state, cartItems, setCardItems }}
    >
      {children}
    </AppContext.Provider>
  );
}

You can then use it this way.

const { state, cartItems, setCartitems } = useAppContext();
Someone Special
  • 12,479
  • 7
  • 45
  • 76
  • This unfortunately doesn't work. I actually tried this method previously, but did again just now to double check. I get: ReferenceError: menuitems is not defined Doing a check on the destructured items in the useAppContext() call, they all return 'undefined' with this method. – User172344 Jan 23 '21 at 19:27
  • Actually, my mistake! I must have just had a syntax error somewhere because this does work for me now. This is actually how I tried to do this originally but my mistake was not having an extra set of {} inside of the value= prop in the provider. – User172344 Jan 23 '21 at 19:36