steven iseki steven iseki - 5 months ago 163
Javascript Question

how to render child components in react.js recursively

I wanted to recursively add a react component from within its own component. I saw this example of a tree component which was mapping through the child TreeNodes and adding child nodes in the same way. Unfortunately it doesn't work at all for me. The idea was to have a simple comment component, and the replies would reuse the same component.

var Comment = React.createClass({
render: function() {
return (
<div className="comment">

{/* text and author */}
<div className="comment-text">
<span className="author">{this.props.author}</span>
<span className="body" dangerouslySetInnerHTML={{__html: this.props.body}} />
</div>

{/* replies */}
<div className="replies">
{
this.props.replies.map(function(reply) {
<Comment body={reply.body} author={reply.author} />
}.bind(this))
}
</div>

</div>
);
}
});


I get the following error message:

Uncaught TypeError: Failed to construct 'Comment': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

here is an example of the JSON data passed to the component.

{ "author" : "Some user",
"body" : "<div>Great work</div>",
"replies" : [ { "author" : "A user replying",
"body" : "<div Yes it was great work</div>"
},
{ "author" : "Another user replying",
"body" : "<div It really was great work!</div>"
}
]
}

Answer

hmm, I didn't expect to sort this issue out so quickly. But I found out if you create the child nodes as an object at the top of the render method, it works fine. Maybe someone more knowledgeable on react.js can give some more feedback on this, but happy to see that it is possible.

var Comment = React.createClass({
  render: function() {    

    var replies = "";
    if(this.props.replies){
      replies = this.props.replies.map(function (reply) {
        return (
          <Comment author={reply.author} body={reply.body} image={reply.image} replies={reply.replies} ></Comment>
        );
      });
    }

    return (
      <div className="comment">

        {/* text and author */}
        <div className="comment-text">
          <span className="author">{this.props.author}</span>         
          <span className="body" dangerouslySetInnerHTML={{__html: this.props.body}} />
        </div>

        {/* replies */}
        <div className="replies">{ replies }</div>

      </div>
    );

  }
});
Comments