title: Using callbacks for parent-to-child communication in React
body: <p>I know that parents communicate with children through props and children to parents by invoking prop-functions.</p>
  
  <p>I've been finding myself in situations where I have a child component where I'd like certain state to be kept. That child will invoke a prop-function and then update its state. Sometimes, though, I'd like the child to only update its state after the parent has finished processing. The parent might make a request to a server async. The traditional approach to handle this in JavaScript is to use a callback.</p>
  
  <p>This feels like another vector for the parent to communicate with the child though. And that strikes me as a violation of React's data flow principles. Is my hesitation here justified? If so, this would just mean hoisting state up to the parent.</p>
  
  <p>Here's an example to illustrate what I'm talking about. We have a form that is toggleable/collapsable. The <code>ToggleableForm</code> either displays a "+" or a <code>Form</code> component based on some state. When the <code>Form</code> propagates a submit event, <code>ToggleableForm</code> proxies that up to the parent, <code>ToggleableFormContainer</code>. We want to wait to collapse the form until we hear back from the server. <code>ToggleableForm</code> hands a callback object to <code>handleFormSubmit</code>. <code>handleFormSubmit</code> then uses those callback functions:</p>
  
  <pre><code>const ToggleableFormContainer = React.createClass({
    handleFormSubmit: function(cb) {
      $.ajax({
        url: self.props.url,
        dataType: 'json',
        cache: false,
        success: cb.onSuccess,
        error: cb.onError,
        },
      });
    },
    render: function() {
      return (
        &lt;ToggleableForm onFormSubmit={this.handleFormSubmit} /&gt;
      );
    },
  })
  
  const ToggleableForm = React.createClass({
    getInitialState: function() {
      return {
        isOpen: false,
      };
    },
    handleOpen: function() {
      this.setState({ isOpen: true });
    },
    handleClose: function() {
      this.setState({ isOpen: false });
    },
    handleSubmit: function(data) {
      this.props.onFormSubmit(data, this.submitCallback);
    },
    submitCallback: {
      onSuccess: function() {
        this.setState({ isOpen: false });
      },
      onError: function() {
        // display error
      },
    },
    render: function() {
      if (this.state.isOpen) {
        return (
          &lt;Form onFormSubmit={this.handleSubmit} onFormClose={this.handleClose} /&gt;
        );
      } else {
        return (
          &lt;button onClick={this.handleOpen}&gt;Open&lt;/button&gt;
        );
      }
    },
  });
  </code></pre>
  
  <p>Thanks!</p>