javascriptreactjsreact-props

Get computed data from multiple children in React parent component


I want to have 2 functional React components:

Currently, in the SummedValue component, I can get the data from Data components alone by children.props.value. However I dont know how to get this value from nested SummedValue components, as it is not a prop.

Basically I think this is related to passing data from the child to the parent, but I cant find the configuration that works

function SummedValue({children}) {
// how can I access this computed value in parent component?
let computedValue = 0;

// Only works for props, not internal values
children.forEach(child => {
    if (child.props.value) {
        value += child.props.value
    }
})

return(
    <div>
        <span>SUMMED NUMBER IS: {computedValue}
        {children}
    </div>
)

}


Solution

  • As we know Context passes through intermediate components while Using and providing context from the same component. The sample code below follows the same principle, please see the output below prior to proceeding with the code.

    Note : This is a naive code, please see the another answer, the code in it is handling the known edge cases as well.

    Browser display of the output

    Please take advantage of the comments enclosed in the code.

    App.js

    import { useContext } from 'react';
    import { RunningSectionSumContext } from './context';
    
    export default function App() {
      return (
        <>
          <SummedValue>
            <Data value={10} />
            <Data value={5} />
            <SummedValue>
              <Data value={20} />
              <Data value={30} />
            </SummedValue>
          </SummedValue>
        </>
      );
    }
    
    function SummedValue({ children }) {
      // Destructuring nested objects.
      const sectionSum = children
        // filter the children with value, the Data components only
        .filter(({ props: { value } }) => value) 
        .map(({ props: { value } }) => value)
        .reduce((a, b) => a + b, 0); // find the section sum
    
      // the statement using the context.
      const runningSectionSum = useContext(RunningSectionSumContext) + sectionSum;
      return (
        <div
          style={{
            border: '2px dotted white',
            margin: 10,
            padding: 10,
            width: '50%',
          }}
        >
          <strong>Running section sum is : {runningSectionSum}</strong>
          <!-- the statement providing the new value to the context -->
          <RunningSectionSumContext.Provider value={runningSectionSum}>
            <!-- while evaluating the children below, the same component
             will be invoked recursively if the child component is
             is a nested SummedValue component. -->
            {children}
          </RunningSectionSumContext.Provider>
          <br />
        </div>
      );
    }
    
    function Data({ value }) {
      return (
        <>
          <br />
          <em>data value : {value}</em>
        </>
      );
    }