Search code examples
javascriptreactjsreactjs-flux

ReactJs aggregate data from components


what's the best way to split a big component into multiple smaller ones and aggregate their data? I would like to access the state of the BillingDataComponent, NameComponent and AddressComponent in the FormComponent.

Example:

var FormComponent = React.createClass({
  _onClick: function() {
    // Access child data here
    var name = ???
    var address = ???
    var billingData = ???

    ActionCreator.updateFormDataOnServer(formDataAggregatedFromChildren);
  },

  render: function() {
    return (
      <div>
        <form>
          <NameComponent name="Maybe the name is already set?" />
          <AddressComponent />
          <BillingDataComponent />
          <button onClick={this._onClick} >Submit</button>
        </form>
      <div>
    );
  }
});

var NameComponent = React.createClass({  
  _onChange: function(e) {
    this.setState({
      value: e.target.value
    });
  },

  render: function() {
    return (
      <div>
        <input type="text" value={this.state.value} onChange={this._onChange} />
      </div>
    );
  }
});

// AddressComponent and BillingDataComponent similiar

Solution

  • You should let the FormComponent own the data and pass it down as props to the other components. When the data should change, the children should propagate the change up to the form:

    var FormComponent = React.createClass({
      getInitialState: function() {
        return {
          name: ""
        };
      },
    
      _onClick: function() {
        // Access child data here
        var name = ???
        var address = ???
        var billingData = ???
    
        ActionCreator.updateFormDataOnServer(formDataAggregatedFromChildren);
      },
    
      _onNameChange: function(name) {
        this.setState({
          name: name
        });
      },
    
      render: function() {
        return (
          <div>
            <form>
              <NameComponent onChange={this._onNameChange} value={this.state.name} />
              <AddressComponent />
              <BillingDataComponent />
              <button onClick={this._onClick} >Submit</button>
            </form>
          <div>
        );
      }
    });
    
    var NameComponent = React.createClass({  
      _onChange: function(e) {
        this.props.onChange(e.target.value);
      },
    
      render: function() {
        return (
          <div>
            <input type="text" value={this.props.value} onChange={this._onChange} />
          </div>
        );
      }
    });
    
    // AddressComponent and BillingDataComponent similiar