Friday, August 14, 2020

React - access ref of child component from parent component

This is how to get access to the ref of a child component from a parent component.  I am working with react-table so this example has references to that.

Environment:
CentOS Linux release 7.3.1611 (Core)
React 16.2
react-table 6.10.3

MyParent.js

const ALL_TOOLS = "";
const TOOL_1 = "tool1";
class MyParent extends Component {
  constructor(props) {
    super(props);

    this.state = {
      error: null,
      rows: [],
      numPages: -1,
      summary: null,
      loading: false,
      filter: ""
    };
  }
  
  /**
   * Allow the parent to get a reference to the child component
   * @param {Object} table
   */
  setRef = table => {
    this.childRef = table;
  };

  /**
   * Event handler for filter selection
   * @param {String} filter
   */
  onFilterSelection = filter => {
    // must put this.fetchData in callback because need to guarantee filter will be updated
    // before calling
    this.setState(
      {
        filter: filter
      },
      () => {
        this.childRef.current.state.page = 0; // force react-table back to page 1
        this.fetchData(this.childRef.current.state);
      }
    );
  };

  /**
   * Fetches data for the table
   * @param {Object} tableState: the react table current table
   */
  fetchData = tableState => {
    // show the loading overlay
    this.setState({ loading: true });
    const sortDir = tableState.sorted[0].desc ? "DESC" : "ASC";
    const offset = tableState.page * tableState.pageSize;
    ...
  };

  render() {
    const { error, rows, numPages, summary, loading } = this.state;
    return (
      <div className="MyParent">
        {!error && (
          <div className="content">
            <div className="left-panel">
              <ul>
                <li
                  onClick={() => this.onFilterSelection(ALL_TOOLS)}
                >All</li>
                <li
                  onClick={() => this.onFilterSelection(TOOL_1)}
                >Tool 1</li>
              </ul>
            </div>
            <div className="right-panel">
              <MyChildTable
                setRef={this.setRef}
                rows={rows}
                numPages={numPages}
                summary={summary}
                loading={loading}
                fetchData={this.fetchData}
              />
            </div>
          </div>
        )}
      </div>
    );
  }
}

export default MyParent;

MyChildTable.js


class MyChildTable extends React.PureComponent {
  constructor(props) {
    super(props);

    // add ref to react table, and pass along to parent
    const { setRef } = this.props;
    this.table = React.createRef();
    setRef(this.table);
  }

  render() {
    const { rows, numPages, summary, loading, fetchData } = this.props;
    const columns = [
      ...
    ];
    return (
      <div className="MyChildTable">
        {summary}
        <ReactTable
          ref={this.table}
          data={rows}
          loading={loading}
          pages={numPages}
          columns={columns}
          defaultSorted={[{ id: "tstamp", desc: true }]}
          multiSort={false}
          className="-striped -highlight"
          showPagination={true}
          showPaginationTop={true}
          showPaginationBottom={true}
          showPageSizeOptions={false} // Only allow 25
          pageSizeOptions={[25]} // Only allow 25
          defaultPageSize={25} // Only allow 25
          manual
          onFetchData={fetchData}
        />
      </div>
    );
  }
}

export default MyChildTable;



This article was helpful.

1 comment:

I appreciate your time in leaving a comment!