在 componentDidMount 中更新状态 属性 未反映为 react-table

Updating state property in componentDidMount not reflecting with react-table

更新状态 属性 data React 组件方法中的值 componentDidMount 不更新 react-table 数据。

在构造函数中调用 getData 工作正常。

App.js

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      data: []
    };
  }

  getData() {
    var MOUNTAINS = [
      {name: "Kilimanjaro", height: 5895, country: "Tanzania"},
      {name: "Everest", height: 8848, country: "Nepal"},
      {name: "Mount Fuji", height: 3776, country: "Japan"},
      {name: "Mont Blanc", height: 4808, country: "Italy/France"},
      {name: "Vaalserberg", height: 323, country: "Netherlands"},
      {name: "Denali", height: 6168, country: "United States"},
      {name: "Popocatepetl", height: 5465, country: "Mexico"}
    ];
    return MOUNTAINS;
  }

  componentDidMount() {
    this.setState({ data : this.getData()}, () => {
      console.table(this.state.data);
    });
  }


  render() {

    const { data } = this.state;
    return <T data={data} />;
  }
}

T.js

export default class T extends Component {
  constructor(props) {
    super(props);
    debugger;
    this.state = {
      data: props.data
    };
  }
  render() {
    return (
      <div>
        <ReactTable
          data={this.state.data}
          columns={[{
                  Header: "Name",
                  accessor: "name"
                },{
                  Header: "Height",
                  accessor: "height"
                },{
                  Header: "Country",
                  accessor: "country"
                }]}
          defaultPageSize={10}
          className="-striped -highlight"
        />
        <br />
      </div>
    );
  }
}

除了 <App/> 组件传递的空数组 data:[] 的初始渲染之外,似乎没有任何东西会调用 T 组件的渲染初始状态。

T 的状态本身在 <App/> 的第一个渲染周期中使用传递给 <T> 的初始道具数据进行初始化。因为 prop data 最初是一个空数组(基于 <App/> 中的初始状态字段 data: []),这将导致 table 显示为空。然而,没有什么会触发 <T> 组件在第一次渲染之后更新(重新渲染),看到 T 将数据从它自己的内部状态(永远不会更新)传递到 <ReactTable> ).

考虑修改 T 组件的 render() 方法,使其通过传递给 <T>data 属性直接呈现 <ReactTable/>,而不是而不是通过执行以下操作通过内部状态:

export default class T extends Component {

  /*
  The changes below make this redundant

  constructor(props) {
    super(props);
    debugger;
    this.state = {
      data: props.data
    };
  }
  */

  render() {
    /* Extract data prop to local variable for subsequent use */
    const data = this.props.data;

    /* If no data prop has been provided, or is of unexpected type, 
       render a "no data" message instead. I've included this to
       illustrate this as a method to handle no or incorrect data 
       for the prop */
    if(!Array.isArray(data)) {
        return (<div>No data to display</div>)
    }

    /* Assume the data prop is of correct type, etc, so now render
    the <ReactTable> with data provided directly from prop rather
    than T's internal state */
    return (
      <div>
        <ReactTable
          data={data}
          columns={[{
                  Header: "Name",
                  accessor: "name"
                },{
                  Header: "Height",
                  accessor: "height"
                },{
                  Header: "Country",
                  accessor: "country"
                }]}
          defaultPageSize={10}
          className="-striped -highlight"
        />
        <br />
      </div>
    );
  }
}

添加 componentDidMountcomponentDidUpdate 方法更新 table 数据。

import React, { Component } from "react";
import ReactTable from "react-table";
import "react-table/react-table.css";

export default class T extends Component {
  constructor(props) {
    super(props);
    debugger;
    this.state = {
      data: props.data
    };
  }

  componentDidMount() {
    this.setState({
      data: this.props.data,
    });
  }

  componentDidUpdate(prevProps){
    if (prevProps !== this.props) {
      this.setState({
        data: this.props.data,
      });
    }
  }

  render() {

    return (
      <div>
        <ReactTable
          data={this.state.data}
          columns={[{
                  Header: "Name",
                  accessor: "name"
                },{
                  Header: "Height",
                  accessor: "height"
                },{
                  Header: "Country",
                  accessor: "country"
                }]}
          defaultPageSize={10}
          className="-striped -highlight"
        />
        <br />
      </div>
    );
  }
}