React How to map an array with input element value changing independently from other input elements in same mapped array

Viewed 21

I am trying to complete my first React project by myself but I am having some problems. I am mapping a JSON file with each having an input field to add item amount to the cart. The problem is when I change one input value, all the input values change. I want them to change independently. I am trying to use id in this case but I don't know the proper way to put that in the code.

Items with input

import React, { useState } from "react";
import "./produce.css";
import produce from "../produce.json";
import { MdArrowDropUp, MdArrowDropDown } from "react-icons/md";

const Produce = () => {
  const [amount, setAmount] = useState(0);

  const handleIncrease = () => {
    if (amount < 20) {
      setAmount(Number(amount) + 1);
    }
  };
  const handleDecrease = () => {
    if (amount > 0) {
      setAmount(Number(amount) - 1);
    }
  };

  const handleChange = (e, id) => {
    setAmount(e.target.value)
  };

  return (
    <div className="produce">
      {produce.map((item) => {
        return (
          <div className="produce_item" key={item.id}>
            <img className="item_img" src={item.img} />
            <div className="produce_explain">
              <div className="produce_explain1">
                <h3>{item.name}</h3>
                {item.iconOrganic && <img src={item.iconOrganic} />}
              </div>
              <div className="produce_explain2">
                {item.organic === "organic" && <h5>{item.organic}</h5>}
                <div className="produce_weight">
                  <h6>approx.</h6>
                  {item.weight}
                </div>
              </div>
              <div className="produce_price">
                <h3>{item.price} $</h3>
              </div>
            </div>
            <div className="produce_buy">
              <button className="produce_cart">Add to Cart</button>
              <div className="produce_number">
                <button className="produce_increase" onClick={handleIncrease}>
                  <MdArrowDropUp />
                </button>
                <input
                  type="text"
                  className="produce_count"
                  value={amount}
                  onChange={(e) => handleChange(e, item.id)}
                />
                <button className="produce_decrease" onClick={handleDecrease}>
                  <MdArrowDropDown />
                </button>
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
};

export default Produce;
1 Answers

Save the amount in the produce list itself. As you are looping through produce to show the value.

import React, { useState } from "react";
import "./produce.css";
import produceListData from "../produce.json";
import { MdArrowDropUp, MdArrowDropDown } from "react-icons/md";

const Produce = () => {
  const [produceList, setProduceList] = useState(produceListData.map(produce => { return {...produce, amount: 0}}));

  const handleIncrease = (id) => {
    if (amount < 20) {
      const newList = produceList.map((item) => {
          if (item.id === id) {
            const updatedItem = {
              ...item,
              amount: item.amount ? Number(item.amount) + 1 : 1,
            };

            return updatedItem;
          }

          return item;
      });
      setProduceList(newList);
    }
  };
  const handleDecrease = () => {
    if (amount > 0) {
      const newList = produceList.map((item) => {
          if (item.id === id) {
            const updatedItem = {
              ...item,
              amount: item.amount ? Number(item.amount) - 1 : 0,
            };
            return updatedItem;
          }
          return item;
      });
      setProduceList(newList);    
    }
  };

  const handleChange = (e, id) => {
    const newList = produceList.map((item) => {
          if (item.id === id) {
            const updatedItem = {
              ...item,
              amount: item.amount ? Number(item.amount) - 1 : 0,
            };
            return updatedItem;
          }
          return item;
      });
      setProduceList(newList);    
  };

  const updateAmount = (amount, id) => {
    
};

  return (
    <div className="produce">
      {produce.map((item) => {
        return (
          <div className="produce_item" key={item.id}>
            <img className="item_img" src={item.img} />
            <div className="produce_explain">
              <div className="produce_explain1">
                <h3>{item.name}</h3>
                {item.iconOrganic && <img src={item.iconOrganic} />}
              </div>
              <div className="produce_explain2">
                {item.organic === "organic" && <h5>{item.organic}</h5>}
                <div className="produce_weight">
                  <h6>approx.</h6>
                  {item.weight}
                </div>
              </div>
              <div className="produce_price">
                <h3>{item.price} $</h3>
              </div>
            </div>
            <div className="produce_buy">
              <button className="produce_cart">Add to Cart</button>
              <div className="produce_number">
                <button className="produce_increase" onClick={(e) => handleIncrease(item.id)}>
                  <MdArrowDropUp />
                </button>
                <input
                  type="text"
                  className="produce_count"
                  value={amount}
                  onChange={(e) => handleChange(e, item.id)}
                />
                <button className="produce_decrease" onClick={(e) => handleDecrease(item.id)}>
                  <MdArrowDropDown />
                </button>
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
};

export default Produce;

Related