javascriptreactjsreact-props

React: Get sum of the child component values in the parent component


The parent component can access the values of the child component, but it is unable to sum the values of each child. The total shows 0 instead of the correct total. enter image description here

I am expecting the correct total of values from each child compoent to show in the Total. Parent and child components as follows.

Parent component

import { useState } from "react"
import SingleEntry from "./SingleEntry"

const TaxSource = ({ type }) => {
    const [valuesFromSingleEntries, setValuesFromSingleEntries] = useState([])

    const sendDataToTaxSource = (value, index) => {
        const newValues = [...valuesFromSingleEntries]
        newValues[index] = value
        setValuesFromSingleEntries(newValues)
    }

    console.log(valuesFromSingleEntries)

    const total = valuesFromSingleEntries.reduce((a, b) => a + b, 0)

    return (
        <>
            <h3>{type}</h3>
            <label
                htmlFor='income'
                className='block text-sm font-medium leading-6 text-gray-900 mt-6'
            >
                Income: {type}
            </label>
            {Array.from({ length: 5 }, (_, i) => (
                <SingleEntry key={i} sendDataToTaxSource={sendDataToTaxSource} />
            ))}

            <p>Total: {total}</p>

        </>
    )
}

export default TaxSource

Child component

import { useState } from "react"

const SingleEntry = ({ sendDataToTaxSource, index }) => {
    const [value, setValue] = useState(0)
    const handleValueChange = (e) => {
        setValue(e.target.value)
    }
    const handleBlur = (e) => {
        let inputValue = e.target.value
        if (!isNaN(inputValue)) {
            setValue(parseFloat(inputValue).toFixed(2))
        }
        sendDataToTaxSource(value, index)
    }
    return (
        <>
            <div className='sm:col-span-4'>
                <div className='flex mb-2 sm:w-128'>
                    <div className='flex flex-col mr-2 w-3/4'>
                        <input
                            type='text'
                            name='description'
                            id='description'
                            placeholder='Enter description'
                            className='border-2 rounded-sm px-3 my-[-3px]  border-gray-300 focus:outline-none focus:ring-1 focus:ring-indigo-600 focus:border-transparent'
                        />
                    </div>
                    <div className='flex flex-col ml-2 w-1/4'>
                        <input
                            type='number'
                            step='0.01'
                            name='value'
                            id='value'
                            value={value}
                            onChange={handleValueChange}
                            onBlur={handleBlur}
                            placeholder='Enter value'
                            className='border-2 rounded-sm pr-3 my-[-3px] border-gray-300 focus:outline-none focus:ring-1 focus:ring-indigo-600 focus:border-transparent text-right'
                        />
                    </div>
                </div>
            </div>
        </>
    )
}
export default SingleEntry

Solution

  • You didn't pass index to SingleEntry so it won't be able to update the right position in the array. The updated code should be:

    {Array.from({ length: 5 }, (_, i) => (
      <SingleEntry key={i} sendDataToTaxSource={sendDataToTaxSource} index={i} />
    ))}
    

    I have copied your code to test in codesandbox, after adding the index it works now: https://codesandbox.io/p/sandbox/get-sum-kqxtcq?file=%2Fsrc%2FApp.js%3A65%2C22