4

Updating the state property data value in react component method componentDidMount not updating the react-table data.

calling the getData in the constructor works fine.

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>
    );
  }
}
ida
  • 545
  • 2
  • 5
  • 20

2 Answers2

1

Adding componentDidMount & componentDidUpdate methods updating the table data.

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>
    );
  }
}
ida
  • 545
  • 2
  • 5
  • 20
0

It doesn't look like there is anything that will invoke rendering of your T component beyond the initial render of the empty array data:[], as passed by the <App/> components initial state.

The state for T itself is initialized with initial prop data passed to <T> on the first render cycle of <App/>. Because the prop data is initially an empty array (based on the initial state field data: [] in <App/>), this will cause the table to appear empty. There is however nothing that trigger's the <T> component to update (re-render) beyond the first render, seeing that T passes data to <ReactTable> from it's own internal state (which never gets updated).

Consider revising the render() method of the T component so that it renders the <ReactTable/> directly via the data prop passed to <T>, rather than via internal state by doing the following:

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>
    );
  }
}
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • Adding `componentDidMount` & `componentDidUpdate` methods to T.js also working. – ida Mar 03 '19 at 06:08