1

Issue: I am trying to fetch the data from a specific button component through onClick but it seems that I am quite confused on how to exactly do it. The button component which was rendered should have the functionality of displaying its specific data on a page when the user clicks on it.

Goal: If a specific menu item button(consisting the menu name, price, and number of available) is clicked, then it should display its menu name, price, and number of available inside the current page or ideally, it can also display on a different page.

My source code:

import * as React from "react";
import { useState } from "react";

import { Stack } from "@mui/material";
import ButtonCategoryStyle from "./ButtonCategoryStyle";

import BBQButtons from "./categoryButtons/BBQButtons";
import BilaoButtons from "./categoryButtons/BilaoButtons";
import ChickenButtons from "./categoryButtons/ChickenButtons";

export default function HomeOrderPage() {
  const categories = ["BBQ", "Bilao", "Chicken"];

  const [myCategory, setMyCategory] = useState("");

  return (
    <div>
      {/* RENDERS THE MENU ITEM BUTTONS: */}
      <Stack spacing={0} direction="row">
        {categories.map((category) => (
          <ButtonCategoryStyle
            title={category.toLocaleUpperCase()}
            key={category}
            onClick={() => setMyCategory(category)}
          />
        ))}
      </Stack>

      <div>
        <p>
          {myCategory === "BBQ" && <BBQButtons />}
          {myCategory === "Bilao" && <BilaoButtons />}
          {myCategory === "Chicken" && <ChickenButtons />}
        </p>
      </div>
    </div>
  );
}

Specific button component (BBQ):

import * as React from "react";
import { Stack } from "@mui/material";
import { Button } from "@mui/material";
import Typography from "@mui/material/Typography";

import ButtonCategoryStyle from "../ButtonCategoryStyle";
import ItemsCategoryButton from "../ItemsCategoryButton";

function preventDefault(event) {
  event.preventDefault();
}

export default function BBQButtons() {
  return (
    <React.Fragment>
      <Stack spacing={0} direction="row" sx={{ mb: 4.5 }}>
        <ItemsCategoryButton
          title="Hito (Small)"
          price="120.00"
          availables="20"
         -- onClick here????? --
        />
        <ItemsCategoryButton
          title="Hito (Medium)"
          price="160.00"
          availables="20"
        />
        <ItemsCategoryButton
          title="Hito (Large)"
          price="210.00"
          availables="20"
        />
        <ItemsCategoryButton
          title="Chicken Paa"
          price="75.00"
          availables="20"
        />

        <ItemsCategoryButton
          title="Chicken Pecho"
          price="85.00"
          availables="20"
        />
      </Stack>

      <Stack spacing={0} direction="row" sx={{ mb: 4.5 }}>
        <ItemsCategoryButton
          title="Chicken Baticulon"
          price="15.00"
          availables="20"
        />
        <ItemsCategoryButton
          title="Chicken Isaw (5 sticks)"
          price="25.00"
          availables="20"
        />
        <ItemsCategoryButton
          title="Chicken Atay"
          price="15.00"
          availables="20"
        />
        <ItemsCategoryButton
          title="Pork Tocino"
          price="10.00"
          availables="20"
        />

        <ItemsCategoryButton
          title="Pork Maskara"
          price="25.00"
          availables="20"
        />
      </Stack>

      <Stack spacing={0} direction="row" sx={{ mb: 4.5 }}>
        <ItemsCategoryButton
          title="Pork Belly"
          price="140.00"
          availables="20"
        />
        <ItemsCategoryButton
          title="Hotdog (Beefies)"
          price="15.00"
          availables="20"
        />
      </Stack>
    </React.Fragment>
  );
}

Full source code in Codesandbox: https://codesandbox.io/s/vibrant-germain-76p1er?file=/src/HomeOrderPage.jsx:0-1069

(Either BBQ, BILAO, or CHICKEN button should be clicked first in order to display the menu items.)

Goal appearance: GOAL APPEARANCE

Old StackOverflow questions I read which still confuses me:

Should I use Axios for this even though I don't have an API yet? I only have local data which are directly defined by me.

Currently, I am confused on where to begin using an onClick event, props, hooks for this one. Thus it would be great to get some helpful guides and tips for this functionality that I am working on.

It would indeed help me a lot as I am exploring React at the moment, thank you very much!!!

Ralph Henry
  • 122
  • 1
  • 13

1 Answers1

2

Most likely you want the data to be dynamic and not hard coded. You should store your items like this

const items = [
  {
    title: "Buffalo Wings",
    price: "200.00",
    availables: "20"
  },
  {
    title: "Battered Chicken (Half)",
    price: "195.00",
    availables: "20"
  },
  {
    title: "Battered Chicken (Whole)",
    price: "380.00",
    availables: "20"
  },
  {
    title: "Garlic Chicken (Half)",
    price: "210.00",
    availables: "20"
  },
  {
    title: "Garlic Chicken (Whole)",
    price: "400.00",
    availables: "20"
  }
];

Then you can map over items to generate the buttons

 <Stack spacing={0} direction="row">
        {items.map((item) => (
          <ItemsCategoryButton
            onClick={() => onSelected(item)}
            key={item.title}
            {...item}
          />
        ))}
      </Stack>

You can keep trace on the selected food on the parent and pass down the setter function to the categories

import * as React from "react";
import { useState } from "react";

import { Stack } from "@mui/material";
import ButtonCategoryStyle from "./ButtonCategoryStyle";

import BBQButtons from "./categoryButtons/BBQButtons";
import BilaoButtons from "./categoryButtons/BilaoButtons";
import ChickenButtons from "./categoryButtons/ChickenButtons";
const categories = ["BBQ", "Bilao", "Chicken"];

export default function HomeOrderPage() {
  const [myCategory, setMyCategory] = useState("");
  const [food, setFood] = useState(null);

  return (
    <div>
      <Stack spacing={0} direction="row">
        {categories.map((category) => (
          <ButtonCategoryStyle
            title={category.toLocaleUpperCase()}
            key={category}
            onClick={() => setMyCategory(category)}
          />
        ))}
      </Stack>

      <div>
        <p>
          {myCategory === "BBQ" && <BBQButtons />}
          {myCategory === "Bilao" && <BilaoButtons />}
          {myCategory === "Chicken" && <ChickenButtons onSelected={setFood} />}
        </p>
      </div>
      {food && food.title}
    </div>
  );
}

The final step is to also pass the onClick function to your custom button component

export default function ButtonCategoryStyle({ title, onClick }) {
  return (
    <Button
      variant="outlined"
      onClick={onClick}
      sx={{
        "&.Mui-selected": {},
        "&.Mui-focusVisible": {
          border: "5px solid #F2A42A"
        },
        ":focus": {
          border: "5px solid #F2A42A"
        },
        ":hover": {
          border: "5px solid #F2A42A",
          backgroundColor: "#green"
        },
        mt: 1,
        ml: 1,
        mb: 8,
        width: 131,
        textTransform: "none",
        backgroundColor: "#1F1D2B",
        borderColor: "#252836",
        borderRadius: 3,
        color: "white",
        height: 49,
        fontFamily: "Barlow Condensed",
        fontSize: "19px"
      }}
    >
      {title}
    </Button>
  );
}

You can them repeat the same process for other categories, note that those categories could contains the items directly.

const categories = [{name: "BBQ", items : []}, {name: "BILAO", items : []}];

codesandbox updated

Reifocs
  • 704
  • 3
  • 16
  • Oh I see, I should make it dynamic and thus using const to define the content of the menu items. Your codesandbox update worked like a charm! May I ask if the same process would work if I try to display the "menu item name", "price", and "num available" to another page through onClick? Like instead showing it to the current page, it will show it to a different page through an onClick manner? @Calfut – Ralph Henry Sep 13 '22 at 08:37
  • The usual way of doing so is to use the url. For example the /products route will list all the product, and the /products/${productId} route will display info about the product having {productId} id. Your button would then redirect to /products/${item.id}. To handle routing in your app you can use React router. The doc has a lot of examples showing off those use cases. – Reifocs Sep 13 '22 at 08:50
  • Oh I see, actually I have react routers on my full main app, but it's only for navigating to different pages with the use of URL too. What I just really want is to pass the object value of the selected menu item into another page. I was thinking of storing the object's property values(name, price, num available) into certain variables. These certain variables would then hold these values and can be displayed into a different page. Does using props work on this functionality? @Calfut – Ralph Henry Sep 13 '22 at 08:58
  • that other page should be on another url? – Reifocs Sep 13 '22 at 12:46
  • if so you can pass state to window.history, with react router it looks like this: let navigate = useNavigate(); navigate("/products/1", { state: product}); and you can access it with: let location = useLocation(); location.state; in the food component but I don't recommend this approach, it will imply serialization and deserialization and makes thing harder than they should be – Reifocs Sep 13 '22 at 12:49
  • Well the other page is not literally on another URL, it is still on the same current URL but it is just rendered within the current page of the current URL. The other page is more likely a page component(in which this other page acts like another area within the current page, more like a "side page"). What I want to do is to just simply display the resulting value of the object(after clicking the menu item) into the other page which exists on the current page @Calfut – Ralph Henry Sep 13 '22 at 14:06
  • We can move this discussion on a chat if you would like @Calfut, you are indeed a big help for me on this project that I am doing. – Ralph Henry Sep 13 '22 at 14:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248021/discussion-between-ralph-henry-and-calfut). – Ralph Henry Sep 13 '22 at 14:07