0

I'm trying to make my react virtualized table sortable. I want the table sort by a particular column when click on a sortable header. I've followed the docs but it dosen't work at all so far. Here is the code:

// @flow
import React from 'react';

import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
import { Table, Column, SortDirection } from 'react-virtualized/dist/commonjs/Table';
import 'react-virtualized/styles.css';
import './table.css';

class TableView extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            sortBy: 'index',
            sortDirection: SortDirection.ASC 
        };
    }
    render() {
  if (this.props.table.length < 1) return null;
  const list = this.props.table[0].tabs.map(function({ info, call_stats, ...a }) {
    var call_stats_lookup = {
      lookup_max: 0,
      lookup_min: 0,
      lookup_median: 0,
      lookup_percentile_75: 0,
      lookup_percentile_90: 0,
      lookup_percentile_95: 0,
      lookup_percentile_99: 0,
      lookup_percentile_999: 0,
      lookup_count: 0
    };
    var call_stats_insert = {
      insert_max: 0,
      insert_min: 0,
      insert_median: 0,
      insert_percentile_75: 0,
      insert_percentile_90: 0,
      insert_percentile_95: 0,
      insert_percentile_99: 0,
      insert_percentile_999: 0,
      insert_count: 0
    };
    if (call_stats !== 'undefined' && typeof call_stats !== 'undefined') {
      var Lookup = call_stats.filter(function(obj) {
        return obj.func === 'lookup';
      });
      var Insert = call_stats.filter(function(obj) {
        return obj.func === 'insert';
      });
      if (Lookup.length !== 0) {
        call_stats_lookup.lookup_max = Lookup[0].time.max;
        call_stats_lookup.lookup_min = Lookup[0].time.min;
        call_stats_lookup.lookup_median = Lookup[0].time.median;
        call_stats_lookup.lookup_percentile_75 = Lookup[0].time.percentile[75];
        call_stats_lookup.lookup_percentile_90 = Lookup[0].time.percentile[90];
        call_stats_lookup.lookup_percentile_95 = Lookup[0].time.percentile[95];
        call_stats_lookup.lookup_percentile_99 = Lookup[0].time.percentile[99];
        call_stats_lookup.lookup_percentile_999 =
          Lookup[0].time.percentile[999];
        call_stats_lookup.lookup_count = Lookup[0].count;
      }
      if (Insert.length !== 0) {
        call_stats_insert.insert_max = Insert[0].time.max;
        call_stats_insert.insert_min = Insert[0].time.min;
        call_stats_insert.insert_median = Insert[0].time.median;
        call_stats_insert.insert_percentile_75 = Insert[0].time.percentile[75];
        call_stats_insert.insert_percentile_90 = Insert[0].time.percentile[90];
        call_stats_insert.insert_percentile_95 = Insert[0].time.percentile[95];
        call_stats_insert.insert_percentile_99 = Insert[0].time.percentile[99];
        call_stats_insert.insert_percentile_999 =
          Insert[0].time.percentile[999];
        call_stats_insert.insert_count = Insert[0].count;
      }
    }
    var call_stats_obj = {
      ...call_stats_insert,
      ...call_stats_lookup
    };
    return { ...a, ...info, ...call_stats_obj };
  });
  const rowGetter = ({ index }) => list[index];
  return (
    <AutoSizer>
      {({ width, height }) => (
        <Table
          ref="Table"
          disableHeader={false}
          width={width}
          headerHeight={50}
          height={height}
          rowHeight={30}
          rowGetter={rowGetter}
          rowCount={list.length}
          sortBy={this.state.sortBy}
          sortDirection={this.state.sortDirection}
          rowClassName={({ index }) => {
              if(index !== -1){
                  return 'ets-table-row';
              } else {
                  return 'ets-table-header';
              }
          }}
          sort={({ sortBy, sortDirection }) => {
              this.setState({sortBy, sortDirection});
          }}
        >
          <Column
            width={150}
            label="Name"
            cellRenderer={({ cellData }) => cellData}
            dataKey="name"
            disableSort={false}
          className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="Memory"
            dataKey="memory"
            cellRenderer={({ cellData }) => cellData}
            disableSort={false}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="Size"
            dataKey="size"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="Type"
            disableSort
            dataKey="type"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="Write concurrency"
            disableSort
            dataKey="write_concurrency"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="Read concurrency"
            disableSort
            dataKey="read_concurrency"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="lookup max time"
            dataKey="lookup_max"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="lookup count"
            dataKey="lookup_count"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="insert max time"
            dataKey="insert_max"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
          <Column
            width={100}
            label="insert count"
            dataKey="insert_count"
            cellRenderer={({ cellData }) => cellData}
            className={'ets-table-cell'}
          />
        </Table>
      )}
    </AutoSizer>
  );
  }
}

export default TableView;

Any help will be appreciated!

1 Answers1

1

Generally, with this sort of question, I suggest you create a Plnkr that demonstrates the problem you're reporting. It's more helpful for people trying to help than a bunch of code pasted into a question.

That being said, you're not actually sorting your data. You're setting state and then expecting react-virtualized to sort the data but that's not how the library works. It never modifies data. Table only even knows about the current sort info so that it can display the right header styles.

You'll need to actually sort the data somewhere (eg componentWillUpdate):

const { list } = this.context;
const sortedList = list
    .sortBy(item => item[sortBy])
    .update(list =>
      sortDirection === SortDirection.DESC
        ? list.reverse()
        : list
    )
  : list;
bvaughn
  • 13,300
  • 45
  • 46
  • I'm getting the error that Cannot read property 'sortBy' of undefined and nowhere in the documentation it explains where sortBy comes from. Is there a generic sortBy somewhere I have to import it or is there already a given sortBy somewhere? – jimmyhuang0904 Jan 20 '20 at 23:33