kuassant
kuassant

Reputation: 131

Button press triggers the last button's press

I'm new to react an am trying to create an app to use in my portfolio. Essentially the program is a menu that has access to different menus(json files: texas_pick.js, breakfast.js...), the program is meant to display the menu options in form of buttons, the buttons' details are retrieved from their respective json file. The problem that I am facing is that when making a click on a menu option the data of the last menu item is retrieved. I programmed the backend to only push the item's name and price to the database, and the frontend, to retrieve this data and display it on a table. The data retrieved is only the last button's and not any others. I believe the problem to possibly be within my button code. Any help/tips/recommendations you could give are greatly appreciated. I clicked every menu item and only the data from the last one was retrieved

import React from 'react' import {useEffect,useState} from 'react' import axios from 'axios' import Texas_Pick from '../../json_files/texas_pick.json' import './Mid_Container.css'

function Mid_Container() { const [items, setItems] = useState(Texas_Pick);

const [order, setOrder] = useState({
    item: '',
    cost: ''
})
const createOrder = () => {
    axios
      .post("http://localhost:5000/orders", order)
      .then(res => {window.location.reload(false)})
      .catch(err => console.error(err));
}

const item1 = items[0];
const item2 = items[1];
const item3 = items[2];
const item4 = items[3];
const item5 = items[4];
const item6 = items[5];


return (
    <div className="Mid_Container">
        <button 
        style={{backgroundImage: `url(${item1.image})`}} 
        value={order.item=item1.item,order.cost=item1.price}             
        onClick={createOrder}
        >
            <p id="pPrice">${item1.price}</p>
            <p id="pItem" >{item1.item}</p>
        </button>

        <button 
        style={{backgroundImage: `url(${item2.image})`}} 
        value={order.item=item2.item,order.cost=item2.price}             
        onClick={createOrder}
        >
            <p id="pPrice">${item2.price}</p>
            <p id="pItem" >{item2.item}</p>
        </button>

        <button 
        style={{backgroundImage: `url(${item3.image})`}} 
        value={order.item=item3.item,order.cost=item3.price}             
        onClick={createOrder}
        >
            <p id="pPrice">${item3.price}</p>
            <p id="pItem" >{item3.item}</p>
        </button>

        <button 
        style={{backgroundImage: `url(${item4.image})`}} 
        value={order.item=item4.item,order.cost=item4.price}             
        onClick={createOrder}
        >
            <p id="pPrice">${item4.price}</p>
            <p id="pItem" >{item4.item}</p>
        </button>

    </div>
)

}

export default Mid_Container

Upvotes: 1

Views: 110

Answers (1)

Ben
Ben

Reputation: 636

I think that you should have this approach:

function SomeComponent() {

  // Mocking your datas
  const [items, setItems] = React.useState([
    {
      price: "1",
      item: "i am the first",
      image: "image1.png",
    },
    {
      price: "7",
      item: "I am the second",
      image: "image2.png",
    },
    {
      price: "3",
      item: "i am the third",
      image: "image3.png",
    },
  ]);
  const [order, setOrder] = React.useState();
  const [myResponse, setMyResponse] = React.useState();

  const createOrder = (clickedItem) => {
    setOrder(clickedItem);
    console.log(clickedItem);
    // axios
    //   .post("http://somewhere", clickedItem)
    //   .then((res) => {
    //     setMyResponse(res); // or setMyResponse(res.json());
    //   })
    //   .catch((err) => console.error(err));
  };

  console.log('Log selected order in render loop ==> ', order);
  console.log('Log response in render loop ==> ', myResponse);
  
  return (
    <div>
      <div className="Mid_Container">
        {items.length && items.map((currItem, index) => {
          return (
            <button
              key={index}
              style={{ backgroundImage: `url(${currItem.image})` }}
              onClick={() => createOrder(currItem)}
            >
              <p id="pPrice">${currItem.price}</p>
              <p id="pItem">{currItem.item}</p>
            </button>
          );
        })}
      </div>
    </div>
  );
}

Mapping on your items with map function, and pass the current item to your onClickEvent. I also think you don't need a value attribute on your buttons. It's also not the place to do operations like you do :)

You also don't have to reload the page in the "then" of your promise. React is made to do SPA (single page application), so in the "then", you can put some code like "setResult(myResponse)" to store in you component the new data you got from your API.

Upvotes: 0

Related Questions