Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add sorting to table with react virtualized?

I am trying to add sorting to my project with the table sorting demo on Github.

My code:

import React from 'react';
import PropTypes from 'prop-types';
import { Table, Column, SortDirection, SortIndicator } from 'react-virtualized';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';

import 'react-virtualized/styles.css';

class NewTable extends React.Component {
  constructor(props) {
    super(props);

    this.dataList = props.list;

    this.state = {
      headerHeight: 50,
      rowHeight: 25,
      rowCount: this.dataList.length,
      height: 400,
      sortBy: 'columnone',
      sortDirection: SortDirection.ASC,
    };

    this.headerRenderer = this.headerRenderer.bind(this);
    this.sort = this.sort.bind(this);
  }

  isSortEnabled() {
    const list = this.dataList;
    const rowCount = this.state;

    return rowCount <= list.length;
  }

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

  headerRenderer({
    dataKey,
    sortBy,
    sortDirection,
  }) {
    return (
      <div>
        Column One
        {sortBy === dataKey &&
          <SortIndicator sortDirection={sortDirection} />
        }
      </div>
    );
  }

  render() {
    const {
      headerHeight,
      height,
      rowHeight,
      sortBy,
      sortDirection,
    } = this.state;

    const list = this.dataList;
    const sortedList = this.isSortEnabled() ?
      (list.sortBy(item => item[sortBy]).update(list => sortDirection === SortDirection.DESC ?
        list.reverse() : list))
      : list;

    return (
      <AutoSizer disableHeight>
        {({ width }) => (
          <Table
            headerHeight={headerHeight}
            height={height}
            rowCount={list.length}
            rowGetter={({ index }) => sortedList[index]}
            rowHeight={rowHeight}
            sort={this.sort}
            sortBy={sortBy}
            sortDirection={sortDirection}
            width={width}
          >
            <Column
              dataKey='columnone'
              headerRenderer={this.headerRenderer}
              disableSort={!this.isSortEnabled}
              width={200}
              flexGrow={1}
            />
          </Table>
        )}
      </AutoSizer>
    );
  }
}

export default NewTable;

My code shows the ASC and DESC arrows flipping up and down when clicked, but the actual sorting does not happen. What am I missing?

I don't really understand where the sorting is happening. I see the functions, but I don't see where the output goes.

Thank you!

EDIT: Data enters as JSON.

like image 718
AO19 Avatar asked Aug 09 '17 13:08

AO19


People also ask

How do you add a sort in react table?

Sorting the React table data. Now, whenever we click any of the table headers, we can sort that particular column in ascending or descending order. To achieve this, we must use an ordering function that knows how to collate and order items. In this case, we will use the sort() function.

Is react table virtualized?

react-virtualized It is exclusively for displaying large datasets on the UI in different formats, like grid, table, and list.


1 Answers

The code snippet you pasted, like the react-virtualized Table demo page, do the sorting inline, within the render function:

const sortedList = this._isSortEnabled()
  ? list
      .sortBy(item => item[sortBy])
      .update(
        list =>
          sortDirection === SortDirection.DESC ? list.reverse() : list
      )
  : list;

This probably isn't what you want for a production app, since it would have to re-sort the data each time a component rendered. Instead you'd probably want to sort the data only once- when the sortBy field or sortDirection change- and then store a sorted version of the data in your component state (or in Redux if you use it).

Table tells you when the data needs to be sorted/resorted by calling the sort prop you provide. In your example above, that means this function is called:

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

Since you're storing the sort criteria in your component state, you can also store the sorted result in state also:

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

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

The only thing that's left is for your rowGetter function to use the sortedList from state rather to retrieve rows.

like image 82
bvaughn Avatar answered Oct 03 '22 00:10

bvaughn