【问题标题】:React component lifecycle componentWillReceiveProps deprecation causes problem with ReduxReact 组件生命周期 componentWillReceiveProps 弃用导致 Redux 出现问题
【发布时间】:2020-07-01 11:48:12
【问题描述】:

我有 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 组件添加了一个状态,因为 getDerivedStateFromProps 将无法正常工作(就我而言已经试过了)。


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

【问题讨论】:

  • 最好的方法是在上面添加另一个组件来管理状态。 Posts 应该是一个无状态组件。
  • 你永远不应该修改props,它违反了 React 单向数据流。 props.posts.unshift(props.newPost);
  • @Rostyslav 啊,当然。忘了那个。对 React 来说还是个新手。

标签: javascript reactjs react-redux deprecated componentwillreceiveprops


【解决方案1】:

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

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

【讨论】:

  • 是的,这解决了。谢谢!但是这里仍然有一些我不明白的魔法。我只是将动作有效负载添加到减速器中的 unshift 中,并从 Posts.js 中删除了所有 3 个以下内容:state、getDerivedStateFromProps 和 UNSAFE_componentWillReceiveProps。我注意到 newPost 需要在 mapStateToProps 中才能正常工作,但我真的不明白为什么。
猜你喜欢
  • 2021-03-20
  • 1970-01-01
  • 2019-10-08
  • 2017-02-11
  • 1970-01-01
  • 2018-11-17
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多