hooking up the data model in ReactJS - syntax

1k Views Asked by At

I'm looking off of the reactjs tutorial on how to build a comment box with react. I get that we are mapping over data, but I cant understand this syntax and part of the code. Would be really helpful if you could explain exactly what is going on here. Specifically, why is props author={comment.author} within the Comment element tag itself and {comment.text} is not.

<Comment author={comment.author}>
    {comment.text}
</Comment>

Context:

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

var commentNodes = this.props.data.map(function (comment) {
  return (
    <Comment author={comment.author}>
      {comment.text}
    </Comment>
  );
});
1

There are 1 best solutions below

3
On BEST ANSWER

Firstly, we should understand, how Comment is defined. From the ReactJS tutorial:

var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        {this.props.children}
      </div>
    );
  }
});

The call to React.createClass defines new component, which could be rendered in the following way:

<Comment author="Pete Hunt">This is one comment</Comment>

<!-- Will be transformed into -->

<div className="comment">
  <h2 className="commentAuthor">
    Pete Hunt
  </h2>
    This is one comment
</div>

As you can see, {this.props.author} has been replaced with Pete Hunt, defined as author property of Comment component, and {this.pros.children} - with Comment's content (just This is one comment in this case).

Now we could move to CommentList declaration. Your commentNodes function is a part of this component, so, I'll show full definition:

var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

Here you can see render function, defined in terms of commentNotes (<div className="commentList"> {commentNodes} </div>). So, what does commentNodes do?

It transforms each comment object into Comment component. Suppose, we have this.props.data defined as:

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

Thus, calling commentNodes will create the following components:

<Comment author="Pete Hunt">This is one comment</Comment>
<Comment author="Jordan Walke">This is *another* comment</Comment>

That will be rendered as:

<div className="comment">
  <h2 className="commentAuthor">
    Pete Hunt
  </h2>
    This is one comment
</div>
<div className="comment">
  <h2 className="commentAuthor">
    Jordan Walke
  </h2>
    This is *another* comment
</div>

UPD

Specifically, why is props author={comment.author} within the Comment element tag itself and {comment.text} is not.

This is pretty simple - by design. You could rewrite Comment component in the following way:

var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        {this.props.content}
      </div>
    );
  }
});

And rewrite CommentList as:

var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author} content={comment.text} />
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

Note also, passing comment text as {this.props.children} allows you to create Comment with nested elements, not only with text.