Home > Back-end >  Save a specific value from an array of object and store them individually into another state to get
Save a specific value from an array of object and store them individually into another state to get

Time:11-21

In addition to this here.

What I want to happen is to only get [434] instead of ['','4','43','434'] So I can .reduce the array to get the sum.

My method on storing the array object to another state is this

 const [amountToPay, setAmountToPay] = useState("")
 console.log("AMOUNT TO PAY", amountToPay)
 useEffect(() => {
   serviceItem.map((item) => (
     setAmountToPay([...amountToPay, item.amountToPay])
   ))
 }, [serviceItem])

 useEffect(() => {
   serviceItem.map((item) => (
     setAmountToPay([...amountToPay, item.amountToPay])
   ))
 }, [serviceItem])

You can check the whole code here CodeSandbox code.Any help is appreciated :)

CodePudding user response:

There are several things I suggest you to do:

  1. Add some id property to your serviceItem. You can use UUID, nanoid, or even Date.now()
  2. Remove const [amountToPay, setAmountToPay] = useState([]);
  3. Use values directly from serviceItem collection. In order to do this you need to create onChange handler, it will be something like this

const handleChange = (id) => (nextAmount) => {
    setServiceList(prevValue => {
       return prevValue.map(item => item.id === id ? { ...item, amount: nextAmount } : item) 
    }) 
}

And amount to pay can be easily got from serviceItem collection, without effects or other states

const procedurePriceTotal = serviceItem.reduce(
    (acc, item) => (acc = acc   item.amount),
    0
);

CodePudding user response:

this is happening because you are setting serviceItem on onChange method and use passed serviceItem as deps array to useeffect in which you are setting amountToPay. so on every change it's appending in array

Rather then setting amount in useEffect, make a method and call on remove/add button so it will only call after user is finished typing. you can also place a button 'Save' or 'calculate Amount' and call handleSetAmountToPAY method which will update amount.

import React, { useState, useMemo, useEffect } from "react";

export default function App() {
  //Values
  const [serviceItem, setServiceList] = useState([
    { serviceValue: "", quantityValue: "", amountToPay: "" }
  ]);
  console.log("SERVICE ITEM", serviceItem);

  //Add item function
  const handleItemAdd = () => {
    setServiceList([
      ...serviceItem,
      { serviceValue: "", quantityValue: "", amountToPay: "" }
    ]);
    handleSetAmountToPAY(serviceItem)
  };

  //Remove item function
  const handleItemRemove = (index) => {
    const list = [...serviceItem];
    list.splice(index, 1);
    setServiceList(list);
    handleSetAmountToPAY(list)
  };

  //Get Values
  const handleGetValues = (e, index) => {
    const { name, value } = e.target;
    const list = [...serviceItem];
    list[index][name] = value;
    setServiceList(list);
  };

  //Saving state to another state
  const [amountToPay, setAmountToPay] = useState([]);
  console.log("AMOUNT TO PAY", amountToPay);
  const handleSetAmountToPAY =  (list) => {
    list && list.map((item) =>
      setAmountToPay([...amountToPay, item.amountToPay])
    );
  }

  //Add total amount
  const procedurePriceTotal = amountToPay.reduce(
    (index, value) => (index = index   value),
    0
  );
  console.log("TOTAL PRICE", procedurePriceTotal);

  return (
    <div className="App">
      {serviceItem.map((singleItem, index) => (
        <div >
          <div >
            <div >
              <label>
                Service <span >*</span>
              </label>
              <input
                name="serviceValue"
                type="text"
                
                value={singleItem.serviceValue}
                placeholder="Tooth Extraction"
                onChange={(e) => {
                  handleGetValues(e, index);
                }}
              />
            </div>
          </div>
          <div >
            <div >
              <label>
                Quantity <span >*</span>
              </label>
              <input
                name="quantityValue"
                type="text"
                
                placeholder="1"
                value={singleItem.quantityValue}
                onChange={(e) => {
                  handleGetValues(e, index);
                }}
              />
            </div>
          </div>
          <div >
            <div >
              <label>
                Amount (₱)<span >*</span>
              </label>
              <input
                name="amountToPay"
                type="number"
                
                placeholder="500"
                value={singleItem.amountToPay}
                onChange={(e) => {
                  handleGetValues(e, index);
                }}
              />
            </div>
          </div>
          <div >
            <div >
              <br />
              {serviceItem.length !== 1 && (
                <button
                  type="submit"
                  onClick={() => handleItemRemove(index)}
                  className="btn btn-primary rx-pr"
                >
                  <i className="fas fa-plus" /> Remove Item
                </button>
              )}
            </div>
          </div>
        </div>
      ))}

      {/* Add Item */}
      <div className="add-more-item rx-pr">
        <button
          type="submit"
          onClick={handleItemAdd}
          className="btn btn-primary rx-pr"
        >
          <i className="fas fa-plus" /> Add Item
        </button>
      </div>
    </div>
  );
}
  • Related