Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Virtualized - Table Example - How do I make it work?

I've been struggling to make this react virtualized table example work & seriously starting to doubt my sanity. I've created a react app and I'm just trying to render the example table inside App.js with this:

class App extends Component {
    render() {
        var data = [1,2,3,4,5,6,7,8,9,10];
        return (
            <TableExample
                list={data}
            />
        );
    }
}

React keeps saying list isn't defined - it seems obvious I'm not getting the data into the component the right way. I haven't been able to understand the example code, what props need to be passed in and what they should be named. Sorry for the stupid question but I've been stuck forever not knowing where else to find an answer. The table example code is below:

/** @flow */
import Immutable from 'immutable';
import PropTypes from 'prop-types';
import * as React from 'react';
import {
  ContentBox,
  ContentBoxHeader,
  ContentBoxParagraph,
} from '../demo/ContentBox';
import {LabeledInput, InputRow} from '../demo/LabeledInput';
import AutoSizer from '../AutoSizer';
import Column from './Column';
import Table from './Table';
import SortDirection from './SortDirection';
import SortIndicator from './SortIndicator';
import styles from './Table.example.css';

export default class TableExample extends React.PureComponent {
  static contextTypes = {
    list: PropTypes.instanceOf(Immutable.List).isRequired,
  };

  constructor(props, context) {
    super(props, context);

    const sortBy = 'index';
    const sortDirection = SortDirection.ASC;
    const sortedList = this._sortList({sortBy, sortDirection});

    this.state = {
      disableHeader: false,
      headerHeight: 30,
      height: 270,
      hideIndexRow: false,
      overscanRowCount: 10,
      rowHeight: 40,
      rowCount: 1000,
      scrollToIndex: undefined,
      sortBy,
      sortDirection,
      sortedList,
      useDynamicRowHeight: false,
    };

    this._getRowHeight = this._getRowHeight.bind(this);
    this._headerRenderer = this._headerRenderer.bind(this);
    this._noRowsRenderer = this._noRowsRenderer.bind(this);
    this._onRowCountChange = this._onRowCountChange.bind(this);
    this._onScrollToRowChange = this._onScrollToRowChange.bind(this);
    this._rowClassName = this._rowClassName.bind(this);
    this._sort = this._sort.bind(this);
  }

  render() {
    const {
      disableHeader,
      headerHeight,
      height,
      hideIndexRow,
      overscanRowCount,
      rowHeight,
      rowCount,
      scrollToIndex,
      sortBy,
      sortDirection,
      sortedList,
      useDynamicRowHeight,
    } = this.state;

    const rowGetter = ({index}) => this._getDatum(sortedList, index);

    return (
      <ContentBox>
        <ContentBoxHeader
          text="Table"
          sourceLink="https://github.com/bvaughn/react-virtualized/blob/master/source/Table/Table.example.js"
          docsLink="https://github.com/bvaughn/react-virtualized/blob/master/docs/Table.md"
        />

        <ContentBoxParagraph>
          The table layout below is created with flexboxes. This allows it to
          have a fixed header and scrollable body content. It also makes use of{' '}
          <code>Grid</code> for windowing table content so that large lists are
          rendered efficiently. Adjust its configurable properties below to see
          how it reacts.
        </ContentBoxParagraph>

        <ContentBoxParagraph>
          <label className={styles.checkboxLabel}>
            <input
              aria-label="Use dynamic row heights?"
              checked={useDynamicRowHeight}
              className={styles.checkbox}
              type="checkbox"
              onChange={event =>
                this._updateUseDynamicRowHeight(event.target.checked)
              }
            />
            Use dynamic row heights?
          </label>

          <label className={styles.checkboxLabel}>
            <input
              aria-label="Hide index?"
              checked={hideIndexRow}
              className={styles.checkbox}
              type="checkbox"
              onChange={event =>
                this.setState({hideIndexRow: event.target.checked})
              }
            />
            Hide index?
          </label>

          <label className={styles.checkboxLabel}>
            <input
              aria-label="Hide header?"
              checked={disableHeader}
              className={styles.checkbox}
              type="checkbox"
              onChange={event =>
                this.setState({disableHeader: event.target.checked})
              }
            />
            Hide header?
          </label>
        </ContentBoxParagraph>

        <InputRow>
          <LabeledInput
            label="Num rows"
            name="rowCount"
            onChange={this._onRowCountChange}
            value={rowCount}
          />
          <LabeledInput
            label="Scroll to"
            name="onScrollToRow"
            placeholder="Index..."
            onChange={this._onScrollToRowChange}
            value={scrollToIndex || ''}
          />
          <LabeledInput
            label="List height"
            name="height"
            onChange={event =>
              this.setState({height: parseInt(event.target.value, 10) || 1})
            }
            value={height}
          />
          <LabeledInput
            disabled={useDynamicRowHeight}
            label="Row height"
            name="rowHeight"
            onChange={event =>
              this.setState({
                rowHeight: parseInt(event.target.value, 10) || 1,
              })
            }
            value={rowHeight}
          />
          <LabeledInput
            label="Header height"
            name="headerHeight"
            onChange={event =>
              this.setState({
                headerHeight: parseInt(event.target.value, 10) || 1,
              })
            }
            value={headerHeight}
          />
          <LabeledInput
            label="Overscan"
            name="overscanRowCount"
            onChange={event =>
              this.setState({
                overscanRowCount: parseInt(event.target.value, 10) || 0,
              })
            }
            value={overscanRowCount}
          />
        </InputRow>

        <div>
          <AutoSizer disableHeight>
            {({width}) => (
              <Table
                ref="Table"
                disableHeader={disableHeader}
                headerClassName={styles.headerColumn}
                headerHeight={headerHeight}
                height={height}
                noRowsRenderer={this._noRowsRenderer}
                overscanRowCount={overscanRowCount}
                rowClassName={this._rowClassName}
                rowHeight={useDynamicRowHeight ? this._getRowHeight : rowHeight}
                rowGetter={rowGetter}
                rowCount={rowCount}
                scrollToIndex={scrollToIndex}
                sort={this._sort}
                sortBy={sortBy}
                sortDirection={sortDirection}
                width={width}>
                {!hideIndexRow && (
                  <Column
                    label="Index"
                    cellDataGetter={({rowData}) => rowData.index}
                    dataKey="index"
                    disableSort={!this._isSortEnabled()}
                    width={60}
                  />
                )}
                <Column
                  dataKey="name"
                  disableSort={!this._isSortEnabled()}
                  headerRenderer={this._headerRenderer}
                  width={90}
                />
                <Column
                  width={210}
                  disableSort
                  label="The description label is really long so that it will be truncated"
                  dataKey="random"
                  className={styles.exampleColumn}
                  cellRenderer={({cellData}) => cellData}
                  flexGrow={1}
                />
              </Table>
            )}
          </AutoSizer>
        </div>
      </ContentBox>
    );
  }

  _getDatum(list, index) {
    return list.get(index % list.size);
  }

  _getRowHeight({index}) {
    const {list} = this.context;

    return this._getDatum(list, index).size;
  }

  _headerRenderer({dataKey, sortBy, sortDirection}) {
    return (
      <div>
        Full Name
        {sortBy === dataKey && <SortIndicator sortDirection={sortDirection} />}
      </div>
    );
  }

  _isSortEnabled() {
    const {list} = this.context;
    const {rowCount} = this.state;

    return rowCount <= list.size;
  }

  _noRowsRenderer() {
    return <div className={styles.noRows}>No rows</div>;
  }

  _onRowCountChange(event) {
    const rowCount = parseInt(event.target.value, 10) || 0;

    this.setState({rowCount});
  }

  _onScrollToRowChange(event) {
    const {rowCount} = this.state;
    let scrollToIndex = Math.min(
      rowCount - 1,
      parseInt(event.target.value, 10),
    );

    if (isNaN(scrollToIndex)) {
      scrollToIndex = undefined;
    }

    this.setState({scrollToIndex});
  }

  _rowClassName({index}) {
    if (index < 0) {
      return styles.headerRow;
    } else {
      return index % 2 === 0 ? styles.evenRow : styles.oddRow;
    }
  }

  _sort({sortBy, sortDirection}) {
    const sortedList = this._sortList({sortBy, sortDirection});

    this.setState({sortBy, sortDirection, sortedList});
  }

  _sortList({sortBy, sortDirection}) {
    const {list} = this.context;

    return list
      .sortBy(item => item[sortBy])
      .update(
        list => (sortDirection === SortDirection.DESC ? list.reverse() : list),
      );
  }

  _updateUseDynamicRowHeight(value) {
    this.setState({
      useDynamicRowHeight: value,
    });
  }
}
like image 939
Trev14 Avatar asked May 15 '18 04:05

Trev14


People also ask

How does a virtualized list work?

The way that most virtualized list components work is that instead of passing a list of elements to render, we instead provide the list with just the number of elements we want to render, how big each element is, and a callback which renders a single item.

How do you implement a table in react?

To create a table in ReactJS, we need to use a package manager (Yarn or npm) to install a react-table and then import the library into our React app by running the following command. import { useTable } from 'react-table'; After the react-table has been installed and imported, we must describe our data and columns.


2 Answers

Looking at some previous questions, it seems that the example is using some components that are not included inside dist package. Thats probably why you are getting undefined error.

Here is the most basic example of Tables in react virtulized:

import React from 'react';
import ReactDOM from 'react-dom';
import { Column, Table } from 'react-virtualized';
import 'react-virtualized/styles.css'; // only needs to be imported once

// Table data as an array of objects
const list = [
  { name: 'Brian Vaughn', description: 'Software engineer' }
  // And so on...
];

// Render your table
ReactDOM.render(
  <Table
    width={300}
    height={300}
    headerHeight={20}
    rowHeight={30}
    rowCount={list.length}
    rowGetter={({ index }) => list[index]}
  >
    <Column
      label='Name'
      dataKey='name'
      width={100}
    />
    <Column
      width={200}
      label='Description'
      dataKey='description'
    />
  </Table>,
  document.getElementById('example')
);

When learning new library, its always best to start with the most simple example then expand on it. Here is the link to the full table docs.

like image 129
Goran Jakovljevic Avatar answered Oct 29 '22 12:10

Goran Jakovljevic


The issue with the example is that in order for contextTypes to work, the parent component needs to define corresponding contextTypes and a getChildContext function.

In the parent component:

class App extends React.Component {
  static childContextTypes = {
    list: PropTypes.instanceOf(Immutable.List).isRequired
  };

  getChildContext() {
    return {
      list
    };
  }

  render() {
    return <TableExample />;
  }
}

Mentioned in this issue; see lines 48-53 and 68-76 of the react-virtualized demo Application.js.

like image 45
Brian Hadaway Avatar answered Oct 29 '22 12:10

Brian Hadaway