0

我有 2 个组件,一个用于将新帖子添加到帖子数组中,另一个组件映射到该帖子数组并在页面上列出它们。

我想用 将新帖子添加到数组的顶部unshift(),但自从componentWillReceiveProps被弃用以来,我一直在努力寻找新getDerivedStateFromProps方法的解决方案。


这是 Postform.js:

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { createPost } from "../actions/postActions";

class PostForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: "",
      body: "",
    };

    this.onChange = this.onChange.bind(this); // Bind onChange event
    this.onSubmit = this.onSubmit.bind(this); // Bind onSubmit event
  }

  // Set state when changing input value
  onChange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }

  onSubmit(e) {
    e.preventDefault();

    const post = {
      title: this.state.title,
      body: this.state.body,
    };

    this.props.createPost(post);
  }

  render() {
    return (
      <div>
        <h1>Add Post</h1>
        <form onSubmit={this.onSubmit}>
          <div>
            <label>Title: </label>
            <br />
            <input
              type="text"
              name="title"
              onChange={this.onChange}
              value={this.state.title}
            />
          </div>
          <br />
          <div>
            <label>Body: </label>
            <br />
            <textarea
              name="body"
              onChange={this.onChange}
              value={this.state.body}
            />
          </div>
          <br />
          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
}

PostForm.propTypes = {
  createPost: PropTypes.func.isRequired,
};

export default connect(null, { createPost })(PostForm);

这是 Posts.js:

import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { fetchPosts } from "../actions/postActions";

class Posts extends Component {
  state = {
    newPost: this.props.newPost,
  };

  componentDidMount() {
    this.props.fetchPosts();
  }

  // The new way I am struggling with
  static getDerivedStateFromProps(props, state) {
    if (props.newPost !== state.newPost) {
      props.posts.unshift(props.newPost);
    }
    return null;
  }

   // The old way, now renamed with UNSAFE_ prefix
  /* UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.newPost) {
      this.props.posts.unshift(nextProps.newPost);
    }
  } */

  render() {
    const postItems = this.props.posts.map((post) => (
      <div key={post.id + Math.random()}>
        <h3>{post.title}</h3>
        <p>{post.body}</p>
      </div>
    ));

    return (
      <div>
        <h1>Posts</h1>
        {postItems}
      </div>
    );
  }
}

Posts.propTypes = {
  fetchPosts: PropTypes.func.isRequired,
  posts: PropTypes.array.isRequired,
  newPost: PropTypes.object,
};

const mapStateToProps = (state) => ({
  posts: state.posts.items,
  newPost: state.posts.item,
});

export default connect(mapStateToProps, { fetchPosts })(Posts);


问题是getDerivedStateFromProps被调用了两次(初始安装和每次渲染),

不像componentWillReceiveProps只调用一次。

这会导致 newPost 被两次添加到数组中,因此它也在页面上显示 double。


我在这里使用 Redux,所以状态应该在 store 中(大部分是),但是我已经为Posts.js组件添加了一个 state,因为getDerivedStateFromProps否则它将不起作用(据我尝试)。


简而言之:如何将 newPost 添加到getDerivedStateFromProps(或其他生命周期方法)内的 props-array 而不会得到双重结果?

4

1 回答 1

1

getDerivedStateFromProps 在调用 render 方法之前被调用,无论是在初始挂载时还是在后续更新时。它应该返回一个对象来更新状态,或者根据反应文档返回 null 以不更新任何内容:https ://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

您似乎已经在使用 redux,因此,一旦您完成了 createPost,为什么在 Redux 商店中更新您的帖子时不执行 array.unshift,因此您的商店将保存 state.posts.items 和您的最新帖子。

于 2020-07-01T12:01:28.257 回答