Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Child-to-parent data flow

Tags:

reactjs

I'm new to React and still learning the basics. Looking at the tutorial here:

http://facebook.github.io/react/docs/tutorial.html#callbacks-as-props

It's explaining how to make a parent respond to events on a child. Here's the relevant bit of code:

var CommentBox = React.createClass({
  handleCommentSubmit: function(comment) {
    // TODO: submit to the server and refresh the list
  },
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList data={this.state.data} />
        <CommentForm
          onCommentSubmit={this.handleCommentSubmit}
        />
      </div>
    );
  }
}

And then in the CommentForm component:

var CommentForm = React.createClass({
  handleSubmit: function() {
    var author = this.refs.author.getDOMNode().value.trim();
    var text = this.refs.text.getDOMNode().value.trim();
    this.props.onCommentSubmit({author: author, text: text});
    this.refs.author.getDOMNode().value = '';
    this.refs.text.getDOMNode().value = '';
    return false;
  },
}

If I'm understanding this correctly, instantiating a <CommentForm/> (without any attributes) would create a broken reference when CommentForm.handleSubmit() tries to call this.props.onCommentSubmit(). The parent must rather do <CommentForm onCommentSubmit={some.function}/>. Is this the official way to do child-to-parent data flow in React? Or is there a more loosely-coupled way? I guess I was hoping for something more akin to Backbone's trigger() and on() functions where one view can change which events it listens to without necessarily creating runtime errors in other views.

like image 575
greim Avatar asked Jun 01 '14 06:06

greim


1 Answers

This is probably the most common form of passing data between components in React. While it's more tightly-coupled than an event-based solution, it's also more explicit (due to less indirection), and React focuses a lot on removing bugs centered around problems with data flow (which can be a problem in large Backbone applications).

Reusable components will often provide an API via their properties. For example, in the CommentForm, it will call the function passed to onCommentSubmit. Components can make this API more explicit by using the propTypes hash. Required properties can be declared with .isRequired, while optional properties leave it off. Components that should function without certain properties should check for the existence of those properties in their handlers, e.g.:

var CommentForm = React.createClass({
  handleSubmit: function() {
    if (this.props.onCommentSubmit) {
      // ...
      this.props.onCommentSubmit(...);
    }
  },
}

Just as passing callbacks around is the most common form of dealing with asynchronous data in Node.js applications, passing functions as properties is the lowest-common-denominator to parent-child component communication in React, and is the best way to ensure any components you build will work with other folks' code. But, just as Node has EventEmitters, promises, fibers, and more, there are plenty of methods you can use to effectively communicate data flow in your React applications. One popular architecture is Flux which offers some more flexibility on the application level while still keeping a clear, one-way data flow; another is the use of an event bus (e.g. with EventEmitter2). Keep in mind, though, what guarantees you're giving up by moving to a more flexible, loosely coupled architecture.

like image 150
Michelle Tilley Avatar answered Sep 29 '22 21:09

Michelle Tilley