在没有刷新浏览器的情况下无法更新MERN上/下投票

问题描述

我正在研究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。尝试使用状态注释来呈现。

您要更新两个景点

  1. 在渲染器中
...
{this.state.comments.map((x,y)=>(
          <div key={y} className="row p-2 border-tlr-3l1">
...
  1. 在您的更新中
...
  updateComment = (updatedComment) => {
    let comments = [...this.state.comments];
...

如果您不更改更新,则下一个更新将清除以前的更新。