skip to Main Content

In addition to this question
I am trying to map individually a state to another state to store the amountToPay object to get the sum of it. The problem is every time it renders the onChange function. It stores every state as object as you can see here: 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 🙂

3

Answers


  1. Chosen as BEST ANSWER

    I was doing it the wrong way. I solved it by mapping the serviceItem then using reduce to get the sum instead of putting it again into a separate array of object then mapping it again to get the sum.

     const newNumberArray = serviceItem.map(function(item) {
        return parseInt(item.amountToPay)
      })
    
     const totalAmountPaid =  newNumberArray.reduce((index,value) =>  index = index + value, 0 )
    

    Thanks for all the help and suggestion!


  2. 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
    );
    
    Login or Signup to reply.
  3. 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 class="row form-row">
              <div class="col-12 col-md-6 col-lg-4">
                <div class="form-group">
                  <label>
                    Service <span class="text-danger">*</span>
                  </label>
                  <input
                    name="serviceValue"
                    type="text"
                    class="form-control"
                    value={singleItem.serviceValue}
                    placeholder="Tooth Extraction"
                    onChange={(e) => {
                      handleGetValues(e, index);
                    }}
                  />
                </div>
              </div>
              <div class="col-12 col-md-6 col-lg-3">
                <div class="form-group">
                  <label>
                    Quantity <span class="text-danger">*</span>
                  </label>
                  <input
                    name="quantityValue"
                    type="text"
                    class="form-control"
                    placeholder="1"
                    value={singleItem.quantityValue}
                    onChange={(e) => {
                      handleGetValues(e, index);
                    }}
                  />
                </div>
              </div>
              <div class="col-12 col-md-6 col-lg-3">
                <div class="form-group">
                  <label>
                    Amount (₱)<span class="text-danger">*</span>
                  </label>
                  <input
                    name="amountToPay"
                    type="number"
                    class="form-control"
                    placeholder="500"
                    value={singleItem.amountToPay}
                    onChange={(e) => {
                      handleGetValues(e, index);
                    }}
                  />
                </div>
              </div>
              <div class="col-12 col-md-6 col-lg-2">
                <div class="add-more">
                  <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>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search