2016-02-10 82 views
4

我想弄清楚如何在ReactJS中编辑注释。我一直在关注this tutorialReactJS编辑注释

有几种说法我有解决方案:

  • 使用可变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()允许动态更新。旧的一系列评论正在被新版本所取代

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
  • 服务器
  • 文本形式作者字段的听力。我们只需要在文本字段
+0

有关如何改进此职位的任何建议?我只想拥有相关信息,因此最容易解决问题 –

+1

您的实际问题是什么?你有许多代码和文本块,但没有一个问号可以在任何地方看到。如果你在某个地方遇到问题,请清楚地说明它是什么。 –

回答

4

它通常不是一个非常好的主意,有与jQuery的碴反应的组分(虽然jQuery的+阵营能起到很好的相互某些任务);我们正在运行一个大规模的React应用程序,并且花了很多时间从我们的早期时间中删除这个实例。

储蓄的评论来看,你需要一个新的端点来处理功能,它应该看起来几乎完全一样app.post('/api/comments')除了没有获得data读取该文件,它应该从req.body得到的数据,这是发布数据到它。要保持相同的网址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> 
    ); 
    } 
});