Structure:
Layer 1 - CommentBox
Layer 2 - CommentList
Layer 3 - Comment
Layer 2 - CommentForm
1. JSX grammar:
var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> CommentBox </div> ); } }); ReactDOM.render( <CommentBox />, document.getElementById('commentBox') );
JSX is an XML-style grammar, and the precompiler converts the grammatical sugar into pure JavaScript:
var CommentBox = React.createClass({ displayName: 'CommentBox', render: function() { return ( React.createElement('div', {className: "commentBox"},"CommentBox") ); } }); ReactDOM.render( React.createElement(CommentBox, null), document.getElementById('commentBox') );
Obviously, JSX grammar is easier to use than simple JavaScript.
React.createClass() creates a new React component, the most important of which is render, which returns a React component tree that will eventually be rendered into HTML.
The <div> tag is not a real DOM node, but an instantiation of a React div component.
ReactDOM.render() instantiates the root component, launches the framework, and injects it into the original DOM element (the second parameter).
2. Add subcomponents CommentList and CompmentForm
var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> CommentBox <CommentList /> <CommentForm /> </div> ); } }); var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> CommentList </div> ); } }); var CommentForm = React.createClass({ render: function() { return ( <div className="commentForm"> CommentForm </div> ); } }); ReactDOM.render( <CommentBox />, document.getElementById('commentBox') );
3. Add Comment components and use props
Data from the parent is available as attributes in the child component and can be accessed through this.props. Named attributes passed to components are accessed through this.props. * and any nested elements are accessed through this.props.children.
var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>CommentBox</h1> <CommentList /> <CommentForm /> </div> ); } }); var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> <Comment author="Alice">This is Alice's comment</Comment> <Comment author="Bruce">This is Bruce's comment</Comment> </div> ); } }); var Comment = React.createClass({ render: function() { return ( <div className="comment"> <h3>{this.props.author}</h3> {this.props.children} </div> ); } }); var CommentForm = React.createClass({ render: function() { return ( <div className="commentForm"> CommentForm </div> ); } }); ReactDOM.render( <CommentBox />, document.getElementById('commentBox') );
4. Add Markdown
Markdown is a simple way to format text inline. Texts surrounded by asterisks will be highlighted.
Use a third-party library, remarkable, which accepts Markdown text and converts it to the original HTML.
Calling toString() converts the text into the original string that remarkable understands.
var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>CommentBox</h1> <CommentList /> <CommentForm /> </div> ); } }); var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> <Comment author="Alice">This is *Alice's* comment</Comment> <Comment author="Bruce">This is Bruce's comment</Comment> </div> ); } }); var Comment = React.createClass({ render: function() { var remarkable = new Remarkable(); return ( <div className="comment"> <h3>{this.props.author}</h3> {remarkable.render(this.props.children.toString())} </div> ); } }); var CommentForm = React.createClass({ render: function() { return ( <div className="commentForm"> CommentForm </div> ); } }); ReactDOM.render( <CommentBox />, document.getElementById('commentBox') );
Question: The asterisk-bound text will only be converted to the contents of <em> and </em> packages (<p>This is <em>Alice's </em> comment </p>), and what is needed is to really render it as HTML.
Solve:
var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>CommentBox</h1> <CommentList /> <CommentForm /> </div> ); } }); var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> <Comment author="Alice">This is *Alice's* comment</Comment> <Comment author="Bruce">This is Bruce's comment</Comment> </div> ); } }); var Comment = React.createClass({ remark: function() { var remarkable = new Remarkable(); var remark = remarkable.render(this.props.children.toString()); return { __html: remark }; }, render: function() { return ( <div className="comment"> <h3>{this.props.author}</h3> <span dangerouslySetInnerHTML={this.remark()} /> </div> ); } }); var CommentForm = React.createClass({ render: function() { return ( <div className="commentForm"> CommentForm </div> ); } }); ReactDOM.render( <CommentBox />, document.getElementById('commentBox') );