ReactJS 用于编辑评论

Posted

技术标签:

【中文标题】ReactJS 用于编辑评论【英文标题】:ReactJS for editing comments 【发布时间】:2016-05-21 08:40:11 【问题描述】:

我试图弄清楚如何在 ReactJS 中编辑 cmets。我一直在关注this tutorial。

我对解决方案有几种理论:

使用可变的state 而不是不可变的props。 与具有loadCommentsFromServerhandleCommentSubmit 函数的CommentBox 组件有关。 loadComments 函数会触发 AJAX 请求,可能发送到我的 comments.json 文件。

这是来自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); 
     ); 
   ); 
 ); 

这是我生成反应组件的主要脚本文件

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(

第一次创建组件时,我们需要从服务器获取JSON的数据,并用最新的数据更新statethis.setState() 允许动态更新。旧的 cmets 数组正在被新数组替换

   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) 
     ); 
   , 

此函数将数据从子组件传递到父组件。它应该提交到服务器并刷新 cmets 列表

   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 服务器的监听 文本表单的作者字段。我们只需要文本字段

【问题讨论】:

关于如何改进这篇文章的任何建议?我只想拥有相关信息,这样最容易解决问题 您的实际问题是什么?您有许多代码和文本块,但在任何地方都看不到一个问号。如果您在某处遇到问题,请明确说明问题所在。 【参考方案1】:

让 jQuery 与 React 组件混搭通常不是一个好主意(尽管 jQuery + React 可以在某些任务上相互配合);我们正在运行一个大规模的 React 应用程序,并且从早期开始就已经花费了很多时间来删除这个实例。

在保存 cmets 方面,您需要一个新的端点来处理该功能,它应该看起来几乎与 app.post('/api/comments') 完全一样,除了不是从读取文件中获取 data,它应该从 req.body 获取数据,这是发布给它的数据。要保持相同的 URL this.props.url,您可以将其设置为 PATCH 端点:app.patch('/api/comments' ...)。我将把实现留给你。 React 的保存功能应该是这样的:Comment 组件应该使用状态来管理它的...状态。单击“编辑”应切换该状态以将contentEditable 设置为true,“编辑”变为“保存”等。实际保存部分应在父组件CommentBox 中定义,并应传递给@ 987654329@ 组件。这是您应该进行的更改以允许编辑的基本想法,它 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> 
     ); 
    
 ); 

【讨论】:

以上是关于ReactJS 用于编辑评论的主要内容,如果未能解决你的问题,请参考以下文章

POST 请求 ReactJS 后列表项未呈现

如何避免 ReactJs 中的 CSS 冲突

如何在 Reactjs 中的谷歌地图上嵌入一个确切的位置

ReactJS-2-props vs state

reactjs 中使用百度Ueditor富文本编辑器

ReactJS编写无状态函数注释