|
@@ -8,16 +8,19 @@ State
|
|
|
- direct reads, write through setState()
|
|
|
- declare initial state in constructo()
|
|
|
|
|
|
+Refs:
|
|
|
+- are called by React during render()
|
|
|
+- (foo) => { this._bar = foo; ) translates to function(foo) { this._bar = foo; }.bind(this);
|
|
|
+
|
|
|
+Events:
|
|
|
+- React events are "synthetic" events, masking the browser behaviour differences
|
|
|
+- https://facebook.github.io/react/docs/events.html
|
|
|
+
|
|
|
JSX:
|
|
|
- "className", not "class"
|
|
|
- knows how to render an array of JSX elements, not just one.
|
|
|
*/
|
|
|
|
|
|
-const commentList = [
|
|
|
- { id: 1, author: "Morgan McCircuit", body: "great picture!" },
|
|
|
- { id: 2, author: "Bending Bender", body: "Excellent stuff" }
|
|
|
-];
|
|
|
-
|
|
|
class Comment extends React.Component {
|
|
|
render() {
|
|
|
return (
|
|
@@ -36,16 +39,61 @@ class Comment extends React.Component {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+class CommentForm extends React.Component {
|
|
|
+ _handleSubmit(event) {
|
|
|
+ // Prevent the page from reloading.
|
|
|
+ event.preventDefault();
|
|
|
+ // this._author/this._body are populated by refs in JSX
|
|
|
+ let author = this._author;
|
|
|
+ let body = this._body;
|
|
|
+ // Since they are elements, we need to take their ".value".
|
|
|
+ this.props.addComment(author.value, body.value);
|
|
|
+ // addComment is called on this.props, meaning it is passed by component parent.
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ return (
|
|
|
+ <form className="comment-form" onSubmit={this._handleSubmit.bind(this)}>
|
|
|
+ <label>Join the discussion</label>
|
|
|
+ <div className="comment-form-fields">
|
|
|
+ <input placeholder="Name:"
|
|
|
+ ref={(input) => { this._author = input; } } /* "this" is CommentForm... *//>
|
|
|
+ <textarea placeholder="Comment:"
|
|
|
+ ref={(textarea) => { this._body = textarea; /* ...because of lexical scope */ } } />
|
|
|
+ </div>
|
|
|
+ <div className="comment-form-actions">
|
|
|
+ <button type="submit">Post comment</button>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
class CommentBox extends React.Component {
|
|
|
constructor() {
|
|
|
super();
|
|
|
this.state = {
|
|
|
- showComments: false
|
|
|
+ showComments: false,
|
|
|
+ comments: [
|
|
|
+ { id: 1, author: "Morgan McCircuit", body: "great picture!" },
|
|
|
+ { id: 2, author: "Bending Bender", body: "Excellent stuff" }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ _addComment(author, body) {
|
|
|
+ const comment = {
|
|
|
+ id: this.state.comments.length + 1,
|
|
|
+ author,
|
|
|
+ body
|
|
|
};
|
|
|
+ // concat(), not push(): push() mutates the data, concat doesn't.
|
|
|
+ // By allocating a new reference, for comments, React detects the change fast.
|
|
|
+ this.setState({comments: this.state.comments.concat([comment])});
|
|
|
}
|
|
|
|
|
|
_getComments() {
|
|
|
- return commentList.map((comment) => {
|
|
|
+ return this.state.comments.map((comment) => {
|
|
|
return (<Comment
|
|
|
author={comment.author}
|
|
|
body={comment.body}
|
|
@@ -81,6 +129,7 @@ class CommentBox extends React.Component {
|
|
|
<div className="comment-box">
|
|
|
<button onClick={this._handleClick.bind(this)}>{buttonText}</button>
|
|
|
<h4 className="comment-count">{this._getCommentsTitle(comments.length)}</h4>
|
|
|
+ <CommentForm addComment={this._addComment.bind(this)} />
|
|
|
{commentNodes}
|
|
|
</div>
|
|
|
);
|