道具从 parent 传递到 child 并且将这些道具设置为状态不会立即生效

Props passed from parent to child and setting those props in state does not work immediately

我正在构建一个应用程序,我从我的 Nodejs 应用程序中获取 "complaints"。然后我将这些投诉作为道具传递给 child 组件。在 child 组件中,我将这些道具设置为 ComponentDidMount() 中的状态。但是 render() 函数首先被调用,因此它不会在屏幕上显示任何内容。状态不会立即设置。请帮忙。我挣扎了2天。

这是parent组件

class Complainer extends Component {
  state = {
    complaints: []
  };

  async componentDidMount() {
    try {
      const user = auth.getCurrentUser();
      console.log(user);
      this.setState({ user });
      if (!user || user.role !== 'complainer') this.props.history.replace('/');
    } catch (ex) {
      window.location = '/login';
    }

    const { data: complaints } = await getComplaints();
    this.setState({ complaints });
  }

  render() {
    const { complaints } = this.state;
    return (
      <React.Fragment>
        <Navbar user={this.state.user} />
        <div className="container">
          <Switch>
            <Route
              path="/complainer/view-all"
              render={props => (
                <AllComplaints complaints={complaints} {...props} />
              )}
            />
            <Route path="/complainer/new-complaint" component={ComplaintForm} />
            <Route path="/complainer/not-found" component={notfound} />
            <Showcase user={this.state.user} />
          </Switch>
          <hr />
        </div>
      </React.Fragment>
    );
  }
}

export default Complainer;

这是child

class AllComplaints extends Component {
  state = {
    data: {
      columns: [
        {
          label: 'location',
          field: 'location',
          sort: 'asc',
          width: 280
        },
        {
          label: 'Title',
          field: 'title',
          sort: 'asc',
          width: 150
        }
      ],

      rows: []
    }
  };

  componentDidMount() {
    const { complaints } = this.props;
    this.setState({ rows: complaints });
  }

  render() {
    const { data } = this.state;
    return (
      <React.Fragment>
        {data.rows && <MDBDataTable striped bordered small data={data} />}
        {!data.rows && <h1>There is no complaints to show</h1>}
      </React.Fragment>
    );
  }
}

export default AllComplaints;

问题是,在状态中,行是空的。即[].在 componentDidMount() 中,我将即将到来的道具设置为这个 "AllComplaints" 组件的状态。

我想将 "props" 值设置为 "this.state.data.rows"。但这并没有发生。设置需要时间,但 render() 首先被调用,所以它在屏幕上什么都不显示。

请帮忙。

如果你想在渲染函数中使用抱怨,你需要在你的状态中初始化它。

您需要为 class 编写构造函数,它接受来自父组件的 props 并使用它来定义行的初始状态。

class AllComplaints extends Component {

    constructor(props) {
        super(props);
        this.state  = {
            data: {
              columns: [
                {
                  label: 'location',
                  field: 'location',
                  sort: 'asc',
                  width: 280
                },
                {
                  label: 'Title',
                  field: 'title',
                  sort: 'asc',
                  width: 150
                }
              ],

              rows: props.complaints
            }
          };
        }
          componentDidMount() {
//commeting below lines as you do not need them as of now.
            //const { complaints } = this.props;
            //this.setState({ rows: complaints });
          }

          render() {
            const { data } = this.state;
            return (
              <React.Fragment>
                {data.rows && <MDBDataTable striped bordered small data={data} />}
                {!data.rows && <h1>There is no complaints to show</h1>}
              </React.Fragment>
            );
          }
        }

        export default AllComplaints;

看来您没有设置 this.state.data.rows 而是设置 this.state.rows 并在 render

中使用 this.state.data.rows

两件事:

如@karahan 所述,您没有正确设置状态。

this.setState({ rows: complaints });

应该是这样的:

this.setState(prevState => { data: { ...prevState.data, rows: complaints } });

但这可能还不够。您正在 parent 的 componentDidMount 中检索您的数据,并在 child 的 componentDidMount 中设置您的状态。但是,child 的 componentDidMount 如果它们同时挂载,则总是第一个 运行,并且只有 运行 一次。这意味着根据您的设置,您的 child 的 props.complaints 有可能在 componentDidMount.

中为空

我会通过不在 child 的组件中使用状态来解决这个问题。很少有充分的理由在多个组件中存储相同的状态(在这种情况下,您在 parent 和 child 中存储相同的东西)。只需使用你的道具,它在你的渲染函数中总是 up-to-date 。您对 MDBDataTable 的渲染应该看起来像这样:

<MDBDataTable striped bordered small data={{ ...this.state.data, rows: this.props.complaints }} />

如果出于某种原因你绝对必须将 complaints 存储在 child 的状态中,你应该取而代之的是在 child 中获取数据,或者查看 getDerivedStateFromPropscomponentDidUpdate。但是,您不太可能需要这样的设置。