【问题标题】:React Virtualized - Table Example - How do I make it work?React Virtualized - 表示例 - 我如何使它工作?
【发布时间】:2018-10-24 19:30:39
【问题描述】:

我一直在努力让this react virtualized table example 工作,并且开始严重怀疑我的理智。我创建了一个反应应用程序,我只是想用这个在 App.js 中呈现示例表:

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

React 一直说 list 没有定义 - 很明显我没有以正确的方式将数据放入组件中。我一直无法理解示例代码,需要传入哪些道具以及它们应该命名的内容。抱歉这个愚蠢的问题,但我一直被困住,不知道在哪里可以找到答案。表格示例代码如下:

/** @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,
    });
  }
}

【问题讨论】:

  • 你成功了吗?
  • 还没有,我已经开始构建我自己的版本,尽可能少的依赖,但还没有完全完成。 @shinzou

标签: react-virtualized


【解决方案1】:

这个例子的问题是,为了让contextTypes工作,父组件需要定义对应的contextTypes和一个getChildContext函数。

在父组件中:

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

  getChildContext() {
    return {
      list
    };
  }

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

this issue中提到;请参阅 react-virtualized 演示 Application.js 的 48-5368-76 行。

【讨论】:

    【解决方案2】:

    查看之前的一些问题,该示例似乎使用了一些未包含在 dist 包中的组件。这可能就是您收到未定义错误的原因。

    这是 React virtulized 中 Tables 的最基本示例:

    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')
    );
    

    在学习新库时,最好从最简单的示例开始,然后对其进行扩展。这是full table docs.的链接

    【讨论】:

      猜你喜欢
      • 2018-07-13
      • 2017-06-11
      • 2021-05-25
      • 1970-01-01
      • 2017-07-26
      • 2012-05-01
      • 1970-01-01
      • 2017-01-29
      相关资源
      最近更新 更多