title: Keeping track of and incrementing states based off of values within child components [React]
body: <p>I'm using a form and two spans to increment/decrement multiple inputs. Each time the form is modified (determined thru onclick), I want to update the sum accordingly. I tried implementing the setState function correctly so as to account for React's state call batching; but it doesn't seem to help (if you run this with console.log, you'll notice that the information is a step behind). I believe it stems from trying to get the value of <code>inputField</code> (top of onClick function &amp; very scuffed implementation). However, I'm not sure how to get and increment this information otherwise. I'm relatively new to React, so even some insight on how I should be structuring this would be helpful (as this poor design seems to be the root of my issues).</p>
  <p>- Thanks in advance</p>
  <pre><code>import React, { Component, PureComponent } from &quot;react&quot;;
  
  function App() {
    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;Parent /&gt;
      &lt;/div&gt;
    );
  }
  
  class Parent extends PureComponent {
    state = {
      formState: {
        // list all objectives here
        firstObjective: [0, 10],
        secondObjective: [0, 30],
        thirdObjective: [0, 1],
      },
      runningTotal: 0,
    };
  
    onClick = event =&gt; {
      var inputField = event.target;
      while (inputField.tagName !== 'INPUT') {
        inputField = inputField.nextElementSibling;
      }
      this.setState((prevState) =&gt; {
        return {
          formState: {
            ...prevState.formState,
            [inputField.name]: [
              (event.target.className === 'arrow down') ?
                Number(Math.max(inputField.value - 1, 0)) :
                Number(inputField.value) + 1,
              Number(inputField.className)
            ]
          }
        }
      });
  
      // ref all objectives here
      var objectives = [
        this.state.formState.firstObjective,
        this.state.formState.secondObjective,
        this.state.formState.thirdObjective
      ];
      console.log(objectives);
  
      var sum = 0;
      for (let i = 0; i &lt; objectives.length; i++) {
        sum += Math.max(Number(objectives[i][0]) - 1, 0) * Number(objectives[i][1]);
      }
      this.setState({
        runningTotal: sum
      });
    }
  
    render() {
      const { formState } = this.state;
      return (
        &lt;div&gt;
          &lt;Form
            formState={formState}
            onClick={this.onClick}
            runningTotal={this.state.runningTotal}
          /&gt;
        &lt;/div&gt;
      );
    }
  }
  
  class Field extends Component {
    state = { inputFieldValue: 0, }
  
    increment(event) {
      this.props.onClick(event, this.inputFieldValue);
    }
  
    render() {
      return (
        &lt;div&gt;
          &lt;div className=&quot;field&quot;&gt;
            &lt;label htmlFor={this.props.name}&gt;{this.props.label}&lt;/label&gt;
            &lt;div className=&quot;numInput&quot;&gt;
              &lt;span className=&quot;arrow up&quot; onClick={this.props.onClick} /&gt;
              &lt;span className=&quot;arrow down&quot; onClick={this.props.onClick} /&gt;
              &lt;input type=&quot;text&quot; name={this.props.name} value={this.props.value} className={this.props.className} readOnly /&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  
  class Form extends Component {
    render() {
      return (
  
        &lt;&gt;
          &lt;form className=&quot;form&quot;&gt;
            &lt;fieldset&gt;
              &lt;Field
                name=&quot;firstObjective&quot; // must match firstObjective
                label=&quot;First Objective&quot;
                value={this.props.formState.firstObjective[0]}
                className={this.props.formState.firstObjective[1]}
                onClick={this.props.onClick} /&gt;
              &lt;Field
                name=&quot;secondObjective&quot; // must match secondObjective
                label=&quot;Second Objective&quot;
                value={this.props.formState.secondObjective[0]}
                className={this.props.formState.secondObjective[1]}
                onClick={this.props.onClick} /&gt;
              &lt;Field
                name=&quot;thirdObjective&quot; // must match third objective
                label=&quot;Third Objective&quot;
                value={this.props.formState.thirdObjective[0]}
                className={this.props.formState.thirdObjective[1]}
                onClick={this.props.onClick} /&gt;
            &lt;/fieldset&gt;
          &lt;/form&gt;
          &lt;div className=&quot;total&quot;&gt;Total: {this.props.runningTotal}&lt;/div&gt;
        &lt;/&gt;
      );
    }
  };
  
  export default App;
  </code></pre>