问题描述
我正在研究MERN堆栈,并试图构建一个论坛应用程序,以便可以对意见进行增/减表决。通过React,通过Express连接到MongoDB的父组件将state(props)传递给子组件,该子组件随后映射道具并还包含上下投票的逻辑。问题是单击投票后,服务器将响应获取操作,而计数器的状态(map方法中的{x.score})没有刷新浏览器就不会更新。
通常,更新状态非常简单。但是,我的代码对于我的基本技能变得有点笨拙。我的问题是:1.如何更改此代码,以便在不手动刷新浏览器的情况下更新计数器的状态。 2.该代码的整体架构是否正确,即在这种情况下应避免将prop传递给子组件?应该使用钩子和useEffect代替吗?或者,即使我应该更改返回中的点击逻辑?
我很难找到有关MERN投票的任何综合互联网资源。另外,我更希望通过stackblits或其他示例来建立示例,但是,此代码取决于mongoDB源和express服务器。
子组件:
constructor(props){
super(props);
this.state={
comments: this.props.comments,}
}
upVote = (x) => {
const user = accountService.userValue;
if (user) {
fetch(`http://localhost:4000/posts/comment/${x}/upVote`,{
method: 'PUT',headers: {
'Accept': 'application/json,text/plain,*/*','Content-Type': 'application/json'
},body: JSON.stringify({user :user.id})
})
.then((res) => {
if (res.success) {
this.updateComment(res.comment);
} else {
console.log('oops: ' + res.message);
}
})
.catch((err) => {
console.log(err);
});
} else {
alert('Please sign up to Vote!');
}
};
updateComment = (updatedComment) => {
let comments = [...this.props.comments];
comments.forEach((comment,index) => {
if (comment._id === updatedComment._id) {
comments[index] = updatedComment;
}
});
this.setState({ comments });
};
...
render(){
return(
...
{this.props.comments.map((x,y)=>(
<div key={y} className="row p-2 border-tlr-3l1">
<div className="col-1 d-flex align-items-center">
<div className="rank">{x.score}</div>
<div className="Votes"></div>
<i className={`fas fa-thumbs-up ${user && x.upVotedby.includes(user.id) ? 'upVoted' : ''}`} onClick={this.upVote.bind(this,x._id)}></i>
<i className={`fas fa-thumbs-down ${user && x.downVotedby.includes(user.id) ? 'downVoted' : ''}`} onClick={this.downVote.bind(this,x._id)}></i>
</div>
<div className="col-11">
<p className="lead mb-0"> {x.comment_body}</p>
<small className="color-3">posted by <span className="color-1l">{x.userName}</span></small>
<small className="color-3"> on {moment(x.createdAt).format('MM/DD/YYYY')}</small>
</div>
</div>
))}
解决方法
您正在更新状态注释,但是当您进行渲染时,您正在使用this.props.comments
。尝试使用状态注释来呈现。
您要更新两个景点
- 在渲染器中
...
{this.state.comments.map((x,y)=>(
<div key={y} className="row p-2 border-tlr-3l1">
...
- 在您的更新中
...
updateComment = (updatedComment) => {
let comments = [...this.state.comments];
...
如果您不更改更新,则下一个更新将清除以前的更新。