简体   繁体   English

更新到状态后,React组件不会重新渲染

[英]React component doesn't rerender after update to state

I have a form to submit a new comment to the comment array this.state.comments. 我有一个表单可以向评论数组this.state.comments提交新评论。

In the same component I want to render these new comments. 在同一组件中,我要呈现这些新注释。 But for some reason my component doesn't rerender when I add a new comment. 但是由于某种原因,当我添加新评论时,我的组件不会重新呈现。 I can only see it when I navigate to a different page and and come back to it. 我只有在导航到其他页面并返回页面时才能看到它。 So the state is definitely updated. 因此状态肯定已更新。

Below is my component, any idea why? 以下是我的组件,知道为什么吗?

class SinglePost extends React.Component {
    constructor(props) {
        super(props)
        const id = props.params.id - 1;
        this.state = props.messages[id];

        this.submitHandler = this.submitHandler.bind(this);
    }

    submitHandler(event) {
        event.preventDefault();
        let target = event.target;
        let comment = target.comment.value,
            user = target.user.value,
            timestamp = new Date,
            id = this.state.id,
            cmtId = this.state.comments.length ? (this.state.comments.length + 1) : 1

        this.props.postNewComment({ id, user, comment, cmtId });
    }

    render() {
        const post = this.state;
        let hour = post.timestamp.getHours();
        hour = hour > 12 ? `${hour - 12}` : hour === 0 ? '12' : `${hour}`;

        let minute = post.timestamp.getMinutes();
        minute = hour > 12 ? `${minute}pm` : `${minute}am`;

        return (
            <div>
                <Link to='/'><button className="btn btn-secondary">Back to Posts</button></Link>
                <h3>{post.title}</h3>
                <p>By: {post.user} on {hour}:{minute}</p>
                <p>{post.message}</p>
                <h4>Responses</h4>
                {post.comments.length > 0 && post.comments.map(cmt => <SingleCommentBox cmt = {cmt} key = {cmt.id}/>)}
                <div>
                    <form id="new-comment-form" onSubmit={this.submitHandler}>
                        <label className="required">Message:</label>
                        <textarea
                            className="form-control"
                            name="comment"
                            type="text"
                            required />
                        <label className="required">User:</label>
                        <input
                            className="form-control"
                            name="user"
                            type="text"
                            required />
                        <button className="btn btn-success" type="submit">Post Reply</button>
                    </form>
                </div>
            </div>
        )
    }
}

const mapStateToProps = state => {
    return {
        messages: state.messages.messages
    }
}

const mapDispatchersToProps = {
    postNewComment
}

export default connect(mapStateToProps, mapDispatchersToProps)(SinglePost)

Rest of my repo . 回购的其余部分。

It looks like you're initializing your state to be from props in the constructor, but never updating the state when the props change, so the state will never change. 看起来您正在将状态初始化为来自构造函数中的props,但在props更改时永远不会更新状态,因此状态永远不会更改。 To me it like you don't need to use state at all. 对我来说,就像您根本不需要使用state

Something like this, then you don't need a constructor either: 这样的事情,那么您也不需要构造函数:

class SinglePost extends React.Component {

    submitHandler = (event) => {
      event.preventDefault();
      let target = event.target;
      let comment = target.comment.value,
        user = target.user.value,
        timestamp = new Date(),
        id = this.props.params.id - 1;
      const comments = this.props.messages[id].comments;
      const cmtId = comments.length ? (comments.length + 1) : 1;

      this.props.postNewComment({ id, user, comment, cmtId });
    }

    render() {
      const id = props.params.id - 1;
      const post = this.props.messages[id];
      let hour = post.timestamp.getHours();

I agree with Austin that you shouldn't need to use state here. 我同意奥斯丁的观点,您不需要在这里使用状态。 Your inputs here aren't controlled (You aren't handling the state changes of the inputs from your parent component). 您在此处的输入不受控制(您未在处理来自父组件的输入的状态更改)。

If you were however, the correct way to do this is use componentWillReceiveProps . 但是,如果要这样做,正确的方法是使用componentWillReceiveProps

componentWillReceiveProps(nextProps) {
  const id = nextProps.params.id - 1;
  this.setState(() => ({post: nextProps.messages[id]});
}

Another recommendation. 另一个建议。 You can actually just pass down 'post' from your mapStateToProps function by accessing ownProps and passing in the id. 实际上,您可以通过访问ownProps并传递ID来从mapStateToProps函数中传递“ post”。 An example: 一个例子:

const mapStateToProps = (state, ownProps) => {
 return {
   post: state.messages[ownProps.id - 1)
  }
 }    

The main advantage here is your not handing down the entire messages array to each component, which could bad for performance if you have a lot of these components on a single page. 这里的主要优点是您无需将整个message数组传递给每个组件,如果在单个页面上有很多这些组件,则可能会降低性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM