Home > database >  How to create a new product component through onClick of a button in React?
How to create a new product component through onClick of a button in React?

Time:10-11

Goal: Create a new product component through onClick of a button where it would display a modal containing textfields to be filled up with the new product's name and price. We then pass the value of those textfields to the data.jsx (data source for rendering the product components) after clicking the Add button inside the modal in order to create a new instance of data info of the new product.

Problem: I am having trouble on passing the values of the textfields from the modal going to data.jsx since I literally have no clue how to properly pass those values into a plain database file. I think props, hooks, etc. might not work on passing the values.

Modal appearance (after clicking Add New Product button): modal

Modal appearance (with textfield values): modal with values

Modal source code (ModalAddProduct.jsx):

import React from "react";
import { Typography } from "@mui/material";
import {
  BrowserRouter as Router,
  Routes,
  Route,
  useNavigate
} from "react-router-dom";
import { TextField } from "@mui/material";
import { useState } from "react";
import "./ModalStyleAddProduct.css";

function ModalAddProduct({ setOpenModalAddProduct }) {
  const navigate = useNavigate();

  const [itemName, setItemName] = useState("");
  const [itemPrice, setItemPrice] = useState("");

  const navigateToDraftsPage = () => {
    navigate("/draftspage");
  };

  return (
    <div className="modalBackground3">
      <div className="modalContainer3">
        <div className="titleCloseBtn3">
          <button
            onClick={() => {
              setOpenModalAddProduct(false);
            }}
          >
            <Typography sx={{ color: "white" }}>X</Typography>
          </button>
        </div>
        <div className="title">
          <h1 className="modalTitleUp">Add New Item Product</h1>
        </div>
        <div className="body">
          <TextField
            onChange={(g1) => setItemName(g1.target.value)}
            className="inputRounded"
            placeholder="Item Name"
            variant="outlined"
            size="small"
          />
          <TextField
            onChange={(g2) => setItemPrice(g2.target.value)}
            className="inputRounded"
            placeholder="Item Price"
            variant="outlined"
            size="small"
            sx={{ width: 100 }}
          />

        </div>
        <div className="footer">
          <button
            onClick={() => {
              setOpenModalAddProduct(false);
            }}
            id="noBtn3"
          >
            Cancel
          </button>
          <button>Add</button>
        </div>
      </div>
    </div>
  );
}

export default ModalAddProduct;

Database source code (data.jsx):

const data = {
  products: [
    {
      id: "1",
      name: "MacBook",
      price: 1400,
      image: "https://picsum.photos/id/180/2400/1600"
    },
    {
      id: "2",
      name: "Old Car",
      price: 2400,
      image: "https://picsum.photos/id/111/4400/2656"
    },
    {
      id: "3",
      name: "W Shoes",
      price: 1000,
      image: "https://picsum.photos/id/21/3008/2008"
    }
  ]
};
export default data;

Full functioning app in CodeSandbox:

https://codesandbox.io/s/addnewproductitem-button-6mtb1o?file=/src/components/modals/ModalAddProduct.jsx

App inspired and based from YT: https://www.youtube.com/watch?v=AmIdY1Eb8tY

It would indeed help a lot to gather tips and guides on how to handle data passing when it comes to plain database files which only contains a const array of objects.

Thank you very much!

CodePudding user response:

All right... I think the best would be to use useContext or Redux, but you can also pass the props back to the parent (Main.js) from ModalAddProduct.

Where you have your "Add" button:

    <button onClick={sendDataToParent}>Add</button>

now add sendDataToParent function in this file.

  const sendDataToParent = () => {
    props.sendData(itemName, itemPrice);
  };

We are passing all the information we want back to the parent. We could also pass it as an object.

Now back in our main.js file:

  const [updatedProductsList, addProd] = useState(products);

And we will use updatedProductsList in our map function at the bottom. On the first render, it will display your 3 products you have.

And last but not least... Remember the sendData we send (props.sendData)? Let's update our updatedProductsList that we declared using the useState hook.

  const sendData = (name, price) => {
    addProd([...updatedProductList, { name, price }]);
  };

Let's "listen" for sendData from the child. As soon as it is triggered the sendData in the parent will be triggered.

  <ModalAddProduct
            sendData={sendData}
            setOpenModalAddProduct={setModalOpenAddProduct}
  />

Now you need to add an image field for consistency. Ideally, as mentioned before redux could be a good tool to use so you could pass your dummy data there and update them as you go along. Please note if you try to add the new item to the cart it will show an error. It is because the price on your form is a string, not a number. BTW, there is a concept called props drilling in react, hence why redux or useContext are preferable. I hope this is all clear :)

https://codesandbox.io/s/addnewproductitem-button-forked-8qdx9f?file=/src/components/modals/ModalAddProduct.jsx

  • Related