ReactJS FixedDataTable排序和过滤示例不起作用

时间:2016-12-02 12:57:14

标签: reactjs fixed-data-table

我正在尝试遵循这个ReactJS教程:

第1部分:http://4dev.tech/2015/12/reactjs-datatable-with-sort-filter-and-pagination-example-part-1/

第2部分:http://4dev.tech/2016/03/tutorial-sorting-and-filtering-a-reactjs-datatable/

我成功完成了第1部分,我需要一些帮助来完成第2部分。

这是我的第2部分代码:

import React from 'react';
import {Table, Column, Cell} from 'fixed-data-table';

class MyTable extends React.Component {

  constructor(props) {
    super(props);
      this.rows = [{"id":1,"first_name":"William","last_name":"Elliott","email":"welliott0@wisc.edu",
             "country":"Argentina","ip_address":"247.180.226.89"},
              {"id":2,"first_name":"Carl","last_name":"Ross","email":"cross1@mlb.com",
             "country":"South Africa","ip_address":"27.146.70.36"},
              {"id":3,"first_name":"Jeremy","last_name":"Scott","email":"jscott2@cbsnews.com",
             "country":"Colombia","ip_address":"103.52.74.225"},
             ]
    this.state = {
      filteredDataList: this.rows
    };
  }

_renderHeader(label, cellDataKey) {
  return <div>
        <span>{label}</span>
          <div>
            <br />
            <input style={{width:90+'%'}} onChange={this._onFilterChange.bind(this, cellDataKey)}/>
          </div>
      </div>;
}

_onFilterChange(cellDataKey, event) {
  if (!event.target.value) {
    this.setState({
      filteredDataList: this.rows,
    });
  }
  var filterBy = event.target.value.toString().toLowerCase();
  var size = this.rows.length;
  var filteredList = [];
  for (var index = 0; index < size; index++) {
    var v = this.rows[index][cellDataKey];
    if (v.toString().toLowerCase().indexOf(filterBy) !== -1) {
      filteredList.push(this.rows[index]);
    }
  }
  this.setState({
    filteredDataList: filteredList,
  });
}

  render() {
      return <Table
        height={40+((this.rows.length+1) * 30)}
        width={1150}
        rowsCount={this.rows.length}
        rowHeight={30}
        headerHeight={30}
        rowGetter={function(rowIndex) {return this.rows[rowIndex]; }.bind(this)}>
        <Column dataKey="id" width={50} label="Id"
            headerRenderer={this._renderHeader.bind(this)}/>
        <Column dataKey="first_name" width={200} label="First Name" />
        <Column  dataKey="last_name" width={200} label="Last Name" />
        <Column  dataKey="email" width={400} label="e-mail" />
        <Column  dataKey="country" width={300} label="Country" />
      </Table>;
  }
}

module.exports = MyTable;

显示数据表但不显示用于过滤行的输入字段。

除少数警告外,浏览器控制台未显示任何错误:

`rowGetter` will be DEPRECATED in version 0.7.0 of FixedDataTable and beyond. 
Please use the cell API in Column to fetch data for your cells.
Read the docs at: https://fburl.com/FixedDataTable-v0.6
`label` will be DEPRECATED in version 0.7.0 of FixedDataTable and beyond. 
Please use `header` instead.
Read the docs at: https://fburl.com/FixedDataTable-v0.6
`dataKey` will be DEPRECATED in version 0.7.0 of FixedDataTable and beyond. 
Please use the `cell` API to pass in a dataKey
Read the docs at: https://fburl.com/FixedDataTable-v0.6
`headerRenderer` will be DEPRECATED in version 0.7.0 of FixedDataTable and beyond. 
Please use the `header` API to pass in a React Element instead.
Read the docs at: https://fburl.com/FixedDataTable-v0.6

我不知道问题是什么。 谢谢你的时间。

2 个答案:

答案 0 :(得分:6)

虽然这个问题已经有一年了,但最近我遇到了类似的麻烦并且可以分享我的经验。另外,我不知道你对React的熟悉程度是什么,但是我会尝试以初学友好的方式解释,以帮助其他人,所以如果有任何明显的话,请耐心等待。

因此,您获得的浏览器错误是由于另一个答案中提到的API更改造成的。您引用的教程使用的是旧API。新的API更改涉及一些事情。也就是说,您无权再访问rowGetterheaderDataGetterheaderRendererdataKeylabel等。

新API涉及将数据直接提供给单元组件,我将演示。

首先,您现在可以制作自定义单元格,因此您可以将它们设置为具有所需的行为。我们将创建一个文本单元格类MyTextCell来显示网格中的文本,以及一个标题单元格类SortHeaderCell,我们可以点击它来对列进行排序,并显示一个显示排序的箭头订购。您也可以为电子邮件列添加自定义单元格类,以生成电子邮件地址链接。

我将首先介绍排序,因为我认为这更难。这基本上使用与文档中的示例相同的方法。

现在你拥有的数据只是一个数组,很好。然而,文档使用DataListWrapper类,它具有包含数据的_data属性,以及排序索引的另一个_indexMap属性,所以让我们这样做(注意,如果您正在查看文档中的示例) ,我改变了一点):

class DataListWrapper {
  constructor(indexMap, data) {
      this._indexMap = indexMap;
      this._data = data;
  }

  getSize() {
      return this._indexMap.length;
  }

  getObjectAt(index) {
      let sortedIdx = this._indexMap[index];
      return this._data[sortedIdx];
  }
}

您可以将前面提到的自定义单元格类型设置为无状态组件,例如我们的自定义文本单元格:

 const MyTextCell = ({ rowIndex, field, data, ...props }) => {
    return (
        <Cell {...props}>
            {data.getObjectAt(rowIndex)[field]}
        </Cell>
    );
 }

或者,您可以像在此自定义排序标题单元格中一样使它们具有状态。我没有理由拥有其中一个,我只想展示两个选项:

    class SortHeaderCell extends React.Component {
      constructor(props) {
      super(props);
      this._onSortChange = this._onSortChange.bind(this);
     }
    render() {

        let {onSortChange, sortDir, children, ...props } = this.props;
        console.log(this.props)
        return (
          <Cell {...props}>
              <a onClick={this._onSortChange}>
                  {children} {sortDir ? (sortDir === SortTypes.DESC ? '↓' : '↑') : ''}
            </a>
        </Cell>
    );
}
_onSortChange(e) {
    e.preventDefault();
    if (this.props.onSortChange) {
        this.props.onSortChange(
            this.props.columnKey,
            this.props.sortDir ?
                reverseSortDirection(this.props.sortDir) :
                SortTypes.DESC
        );
    }
 }
}

您还需要创建排序类型:

 const SortTypes = {
      ASC: 'ASC',
      DESC: 'DESC',
 };

一种快速反转排序类型的方法:

  function reverseSortDirection(sortDir) {
      return sortDir === SortTypes.DESC ? SortTypes.ASC : SortTypes.DESC;
  }

有一点需要注意 - 我们在标题中有一个_onSortChange方法,用于显示箭头并调用实际对数据进行排序的方法,但该方法将在实际的表组件中。

在你的表格中,你需要做一些事情。

在您的情况下,您的表数据是硬编码的,但最佳做法是通过道具传递它。假设您通过属性获取数据,您将相应地设置StateState并设置默认排序索引(基本上是数据最初排序的方式)。

componentWillReceiveProps(props) {
    this._defaultSortIndexes = [];
    var size = props.myDataArray.length;
    for (var index = 0; index < size; index++) {
        this._defaultSortIndexes.push(index);
    }
    this.setState({ myTableData: props.myDataArray, sortedFilteredDataList: new DataListWrapper(this._defaultSortIndexes, props.myDataArray) }) 
}

因此,现在您的标题知道如何显示箭头以及如何调用表本身的_onSortChange方法。您的表组件也知道如何通过props接收数据数组,并将其放入DataWrapper,并将其添加到状态。所以我们必须在表中创建_onSortChange方法,这实际上将数据包装器中的sortIndexes设置为正确的顺序:

_onSortChange(columnKey, sortDir) {
    var sortIndexes = this._defaultSortIndexes.slice();
    sortIndexes.sort((indexA, indexB) => {
        var valueA = this.state.myTableData[indexA][columnKey];
        var valueB = this.state.myTableData[indexB][columnKey];
        var sortVal = 0;
        if (valueA > valueB) {
            sortVal = 1;
        }
        if (valueA < valueB) {
            sortVal = -1;
        }
        if (sortVal !== 0 && sortDir === SortTypes.ASC) {
            sortVal = sortVal * -1;
        }
        return sortVal;

    });

    this.setState({
        sortedFilteredDataList: new DataListWrapper(sortIndexes, this.state.myTableData),
        colSortDirs: {
            [columnKey]: sortDir,
        },
    });
}

现在,您可以像这样设置列:

     <Column
            columnKey='country'
            header={
                <SortHeaderCell
                    onSortChange={this._onSortChange}
                    sortDir={colSortDirs.country}>
                    Country
                </SortHeaderCell>}
                cell={
                    <MyTextCell
                        data={this.state.sortedFilteredDataList}
                        field="country"
                     />
                }
                width={150}
       />

这几乎是用于排序的。文档演示了使用带有过滤器索引的DataListWrapper以类似的方式过滤。我没有这样做,只是在我的表组件嵌套的组件中过滤了我的数据数组。本质上,我有一个组件负责通过props将数据传递给表组件,并在那里进行过滤。我是这样做的:

在父组件中,我有一个过滤器/搜索方法:

filterSearch(searchTerm) {

    this.setState({
        filteredData: this.state.myData.filter(function (el) {
            return (el.propertyToFilter.includes(searchTerm) || !searchTerm);
        })
    });
}

然后我渲染我的搜索组件和我的表组件:

        <div>
            <div>
                <SearchBox onSearchTermChange={this.filterSearch} />
            </div>

            <br />
            <div className="row">
                <div>
                    <ResultsTable myDataArray={this.state.filteredData} />
                </div>
            </div>
        </div>

我的搜索框组件是:

class SearchBox extends Component{
constructor(props) {
    super(props);


    this.state= {term: ''};
}

render() {
    return (
    <div>
     <input 
     value={this.state.term}
     onChange={(e)=>this.onInputChange(e.target.value)}></input>

    </div>
    )
}

onInputChange(term){
    this.setState({term});
    this.props.onSearchTermChange(term);
}
}
export default SearchBox;

几乎就是这样。您还应该注意,现在不支持fixed-data-table,您应该使用fixed-data-table-2。也就是说,我在固定数据表中完成了上述所有操作,它应该可以工作。

有关文档,官方文档为here

那些链接旧的例子,但有一些错误。新的例子是here

答案 1 :(得分:0)

此问题与您的固定数据表版本有关。请在此处查看此v0.6 API迁移:https://facebook.github.io/fixed-data-table/v6-migration.html