ソースを参照

L5.6: Adding and deleting comments server side.

Frederic G. MARAND 8 年 前
コミット
78a6fd9eb6
1 ファイル変更41 行追加11 行削除
  1. 41 11
      src/comments.js

+ 41 - 11
src/comments.js

@@ -22,21 +22,37 @@ Lifecycle methods:
 - fetch initial data from cWM, start a refresh poll loop from cDM, stop loop from cWU
  - https://facebook.github.io/react/docs/react-component.html
 
+One-way control / data flow: control flows from higher level components down to
+child components, forcing changes to happen reactively.
+- example 1: CommentBox passes _deleteComment as callback to its Comment child
+- example 2: CommentBox passes _addComment as callback to its CommentForm child
+ - both are passed as props.
+- example 3: CommentBox passes author and body props to Comment (in previous versions)
+When a child wants to send data back to the parent it does it through a callback
+provided by the parent as a prop.
+
 JSX:
 - "className", not "class"
 - knows how to render an array of JSX elements, not just one.
  */
 
 class Comment extends React.Component {
+  _handleDelete(event) {
+    event.preventDefault();
+    if (confirm("Are you sure?")) {
+      this.props.onDelete(this.props.comment);
+    }
+  }
+
   render() {
     return (
       <div className="comment">
-        <p className="comment-header">{this.props.author}</p>
+        <p className="comment-header">{this.props.comment.author}</p>
         <p className="comment-body">
-          {this.props.body}
+          {this.props.comment.body}
         </p>
         <div className="comment-footer">
-          <a href="#" className="comment-footer-delete">
+          <a href="#" className="comment-footer-delete" onClick={this._handleDelete.bind(this)}>
             Delete comment
           </a>
         </div>
@@ -86,19 +102,32 @@ class CommentBox extends React.Component {
 
   _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])});
+    jQuery.post("api/comments", {comment})
+      .success(newComment => {
+        // 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([newComment])});
+      });
+  }
+
+  _deleteComment(comment) {
+    jQuery.ajax({
+      method: "DELETE",
+      url: `api/comments/${comment.id}`
+    });
+    const comments = [...this.state.comments];
+    const commentIndex = comments.indexOf(comment);
+    comments.splice(commentIndex, 1);
+    this.setState({comments});
   }
 
   _fetchComments() {
     jQuery.ajax({
       method: "GET",
-      url: "/static/comments.json",
+      url: "/api/comments",
       // Arrow function: keep "this" binding to the class instance.
       success: (comments) => {
         this.setState({comments});
@@ -109,9 +138,10 @@ class CommentBox extends React.Component {
   _getComments() {
     return this.state.comments.map((comment) => {
       return (<Comment
-        author={comment.author}
-        body={comment.body}
-        key={comment.id} />);
+        key={comment.id}
+        comment={comment}
+        onDelete={this._deleteComment.bind(this)}
+      />);
     });
   }