ReactJS 用于编辑评论
Posted
技术标签:
【中文标题】ReactJS 用于编辑评论【英文标题】:ReactJS for editing comments 【发布时间】:2016-05-21 08:40:11 【问题描述】:我试图弄清楚如何在 ReactJS 中编辑 cmets。我一直在关注this tutorial。
我对解决方案有几种理论:
使用可变的state
而不是不可变的props
。
与具有loadCommentsFromServer
和handleCommentSubmit
函数的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
的数据,并用最新的数据更新state
。 this.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 用于编辑评论的主要内容,如果未能解决你的问题,请参考以下文章