ReactJS to edit comments

I am trying to understand how to edit comments in ReactJS. I followed this tutorial .

There are several theories in the solution:

  • Using mutable stateinstead of immutable props.
  • Used with a component CommentBoxthat has loadCommentsFromServerand functions handleCommentSubmit. The function loadCommentslaunches an AJAX request, possibly to my comments.jsonfile.

Here is the corresponding code from the file server.js

var COMMENTS_FILE = path.join(__dirname, 'comments.json'); 

app.get('/api/comments', function(req, res) { 
   fs.readFile(COMMENTS_FILE, function(err, data) { 
     if (err) { /* Print error to console */ } 
     res.json(JSON.parse(data)); 
   }); 
 }); 

// This snippet of code is probably the most important
 app.post('/api/comments', function(req, res) { 
   fs.readFile(COMMENTS_FILE, function(err, data) { 
     if (err) { /* Print error to console */ }
     var comments = JSON.parse(data); 

     var newComment = { 
       id: Date.now(), 
       text: req.body.text, 
     }; 
     comments.push(newComment); 
     fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) { 
       if (err) { /* Print error to console */ }
       res.json(comments); 
     }); 
   }); 
 }); 

Here is my main script file where I create responsive components

var Comment = React.createClass({ 

   render: function() { 
     return ( 
       <div className="comment"> 
         // Trying to change the value of the text box on edit
         <p onChange={this.handleTextChange()}> {this.props.text} </p> 
       </div> 
     ); 
   } 
 }); 

 var CommentBox = React.createClass({

When the component is first created, we need to get data JSONfrom the server and update stateusing the latest data. this.setState()Allows dynamic updates. The old comment array is replaced with the new

   loadCommentsFromServer: function() { 
     $.ajax({ 
       url: this.props.url, 
       dataType: 'json', 
       cache: false, 
       success: function(data) { 
         this.setState({data: data}); 
       }.bind(this), 
       error: function(xhr, status, err) { 
         console.error(this.props.url, status, err.toString()); 
       }.bind(this) 
     }); 
   }, 

.

   handleCommentSubmit: function(comment) { 
     var comments = this.state.data; 
     comment.id = Date.now(); 
     var newComments = comments.concat([comment]); 
     this.setState({data: newComments}); 
     $.ajax({ 
       url: this.props.url, 
       dataType: 'json', 
       type: 'POST', 
       data: comment, 
       success: function(data) { 
         this.setState({data: data}); 
       }.bind(this), 
       error: function(xhr, status, err) { 
         this.setState({data: comments}); 
         console.error(this.props.url, status, err.toString()); 
       }.bind(this) 
     }); 
   }, 
   getInitialState: function() { 
     return {data: []}; 
   }, 
   componentDidMount: function() { 
     this.loadCommentsFromServer(); 
     setInterval(this.loadCommentsFromServer, this.props.pollInterval); 
   }, 
   render: function() { 
     return ( 
       <div className="commentBox"> 
         <h1>Comments</h1> 
         <CommentList data={this.state.data} /> 
         <CommentForm onCommentSubmit={this.handleCommentSubmit} /> 
       </div> 
     ); 
   } 
 }); 

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

. this.state . .

 var CommentForm = React.createClass({ 
   getInitialState: function() { 
     return {text: ''}; 
   }, 
   handleTextChange: function(e) { 
     this.setState({text: e.target.value}); 
   }, 
   // This is also probably an important function
   handleSubmit: function(e) { 
     e.preventDefault(); 
     var text = this.state.text.trim(); 
     this.props.onCommentSubmit({text: text}); 
     this.setState({text: ''}); 
   }, 

value onChange

   render: function() { 
     return ( 
       <form className="commentForm" onSubmit={this.handleSubmit}> 
         <input type="text" value={this.state.text} onChange={this.handleTextChange} /> 
         <input type="submit" value="Post" /> 
       </form> 
     ); 
   } 
 }); 

, CommentBox. url . pollInterval 2 .

 ReactDOM.render( 
   <CommentBox url="/api/comments" pollInterval={2000} />, 
   document.getElementById('content') 
 ); 

,

setTimeout(function() {
    $('.edit').on('click', function() {
        $(this).prev().prop('contentEditable', 'true');
        $(this).prev().focus();
    });
},1000);

setTimeout, . html5 contentEditable true.

JSON .

, onclick

, onChange , .

render: function() { 
  return ( 
    <div className="comment"> 
      <p onChange={this.handleTextChange()}> {this.props.text} </p> 
    </div>  
  ); 
}  

, .

, . , . :

  • npm app.use
  • .
+4
1

, , jQuery React ( jQuery + React ); React .

, , app.post('/api/comments'), , data , req.body, , . url this.props.url, PATCH: app.patch('/api/comments' ...). . React : Comment .... "" , contentEditable true, "" "" .. CommentBox Comment. , , , 100% , , , .

// changes to Comment component
var Comment = React.createClass({
  getInitialState: function() {
    return {
      contentEditable: false,
      buttonText: 'Edit',
      text: this.props.text
    };
  },
  handleButton: function() {   
    var commentTag = this.refs.comment;
    // if the component is currently editable and the text is different from the original, save it
    if (this.state.contentEditable && commentTag.textContent != this.state.text) {
      this.props.onUpdateComment(this.props.id, commentTag.textContent);
    }
    // invert current contentEditable state Save => Edit or Edit => Save
    var editable = !this.state.contentEditable;
    this.setState({
      contentEditable: editable,
      // update the state to reflect the edited text
      text: commentTag.textContent,
      // change button text based on editable state
      buttonText: editable ? 'Save' : 'Edit'
    });
 },
 render: function() {
   return (
     <div className="comment">
       <h2 className="commentAuthor">{this.props.author}</h2>
       <p ref="comment" contentEditable={this.state.contentEditable}>{this.state.text}</p>
       <button onClick={this.handleButton}>{this.state.buttonText}</button>
     </div>
   );
 }
});

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

 // changes to CommentBox
 var CommentBox = React.createClass({
   loadCommentsFromServer: function() {
     $.getJSON(this.props.url)
      .then(function(newComments) {
        this.setState({ data: newComments });
      }.bind(this))
      .fail(function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      });
   }, 
   handleCommentSubmit: function(comment) { 
     var comments = this.state.data; 
     comment.id = Date.now(); 
     var newComments = comments.concat([comment]); 
     this.setState({data: newComments}); 

     $.post(this.props.url, comments)
      .then(function(data) {
        this.setState({ data: data });
      }.bind(this))
      .fail(function(xhr, status, err) {
        this.setState({ data: comments });
        console.error(this.props.url, status, err.toString());
      }.bind(this));
   },
   onUpdateComment: function(id, comment) {
     // clone state, we don't want to alter this directly
     var newData = this.state.data.slice(0);
     newData.forEach(function(item) {
       if(item.id === id) {
         item.text = comment;
       }
     });
     $.ajax({
       url: this.props.url,
       dataType: 'json',
       method: 'PATCH',
       data: newData
     }).then(function(data) {
       this.setState({ data: data });
     }.bind(this));
   },
   getInitialState: function() { 
     return {data: []}; 
   }, 
   componentDidMount: function() { 
     this.loadCommentsFromServer(); 
     setInterval(this.loadCommentsFromServer, this.props.pollInterval); 
   }, 
   render: function() { 
     return ( 
       <div className="commentBox"> 
         <h1>Comments</h1> 
         <CommentList data={this.state.data} /> 
         <CommentForm onCommentSubmit={this.handleCommentSubmit} /> 
       </div> 
     ); 
   } 
 }); 
+4

Source: https://habr.com/ru/post/1628193/


All Articles