7

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.

1 Answer 1

9

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.

Sign up to request clarification or add additional context in comments.

4 Comments

First of all, thank you for the quick reply Brian, appreciate it. But it still did not work. I even used almost all of your code: jsfiddle.net/L69zaLtw/2 , the Error that is being displayed: "list.sortBy is not a function". What am I doing wrong here? Thank you
Ah, makes sense. In my code, the list property is an Immutable.List which has a sortBy function. In your case, if it's an Array, you'll want to use the Array.prototype.sort method instead :)
Is there much of a purpose of the sortBy and sortDirection props if you can just grab them from state in any case?
I'm getting the error TypeError: list.sortBy is not a function, but none of the documents implement sortBy but it's in all the source code. How do I go around this? Maybe I'm not understanding how the dataList is being formatted (or where its being passed from)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.