0

I'm using the most bodacious react-virtualized component in a calendar-like application that I'm working on.

I'm using three grids with ScrollSync like in this example but also using cellRangeRenderer to render "pills" on top of the grid.

The application works very nicely however I am finding that on slower computers that the rendering while scrolling can be pretty slow (there can be around 40 columns by 20 rows and up to 40 or so pills rendered in a single view)

Some of the people that will be using this app actually don't really need virtualization because the overall table of data is not that large. So, what I'd like to do is keep using the general framework that react-virtualized provides but for users with rows < x but just render the whole grid in one go to hopefully improve performance. For users with rows > x then grids will be virtualized as normal.

I know that the cellRangeRenderer just receives a start and end index for rows and columns and then returns an array of divs for each cell of the grid, so I can imagine just sending the start and end index for the entire grid and then the whole grid will be returned. I'm just not sure how to then override the re-render on scroll.

I'd be interested to hear any suggestions or similar experiences.

oldo.nicho
  • 2,149
  • 2
  • 25
  • 39

2 Answers2

1

I would suggest not using react-virtualized components when your row-count is small enough not to require virtualization. It adds complexity, etc. unnecessarily. :)

You could create a fake Grid component that just renders all rows and then conditionally swap between it and the real one based on row count, eg:

import {Grid} from 'react-virtualized';
import FakeGrid from './FakeGrid';

// Your render function
const GridComponent = this.props.rowCount > SOME_THRESHOLD
  ? Grid
  : FakeGrid

return <GridComponent {...gridProps} />
bvaughn
  • 13,300
  • 45
  • 46
  • Thanks @brianvaughn, I will experiment with this. I would like to use as much of the advantages of `react-virtualized` (the `cellRangeRenderer` and `scrollSync` functions in particular) so I'll give your suggestion a go and see how it pans out. Will let you know. As always, thanks for you activeness in this project :-) – oldo.nicho Oct 22 '17 at 02:39
  • because so much of the logic and functionality that I've developed is wrapped up in `react-virtualized` components it would be amazing if there was a way to just render the entire grid once but intercept any calls to re-render. I've tried looking into the source for `Grid` but can't see how to achieve this. Do you have any suggestions? – oldo.nicho Oct 24 '17 at 05:50
  • I guess you could fake this by giving RV a specific width + height + row/col count to force it to render a specific number of rows+cols initially, and then in `componentDidMount` set a state flag that tells render "behave normally now, you're running in a browser". – bvaughn Oct 24 '17 at 16:01
  • Thanks Brian. I ended up just leaving it with virtualisation for all situations. I did eventually manage to hack in a solution for rendering the entire grid using the method you proposed, but render time was very slow. Cheers. – oldo.nicho Nov 07 '17 at 23:34
0

I have a component which wraps the Table from react-virtualized, to which I'm passing a fixedHeight prop (boolean), and using it as follows:

import {
  AutoSizer,
  Table as VirtualizedTable
} from 'react-virtualized';

const Table = (props) => {
  const getHeight = (autoSizerHeight) => {
    const { fixedHeight, headerHeight, rowHeight, rowCount } = props;

    // I'm checking for `rowCount` in order to properly render the `noRowsRenderer` component
    return fixedHeight && rowCount
      ? headerHeight + rowHeight * rowCount
      : autoSizerHeight;
  }
  
  return (
    <AutoSizer
      disableHeight={props.fixedHeight && Boolean(rowCount)}>
      {({ height, width }) => (
        <VirtualizedTable
          ...
          width={width}
          height={getHeight(height)}>
          {props.columnDefs.map(
            (columnDef, columnIndex) => (
              <Column ... />
            )
          )}
        </VirtualizedTable>
      )}
    </AutoSizer>
  );
}

Note:

I'm not opting-out of virtualization, I usually use the fixedHeight prop when I don't want scrolling inside the table, or when the data is paginated and pages are not huge.

Hope it helps :)

Daniel
  • 55
  • 2
  • 11