I have the following requirements to my table:
- Table should have fixed header
- It needs to autosize: for infinite scroll to work the first fetch should get sufficient amount of data for scroll to appear at all.
- table body should work as infinite loader: when scrolled to the end of the list table body should show loading indicator and load more rows
My assumptions are as follows:
- as user will scroll through possibly large sets of data I should virtualize lists (react-virtualized seems to be the only good option for me)
- as we currently have react-table I want to keep it (it has great mechanism of declaring table rows, columns, accessing data and filtering + sorting)
- As we use material ui I need to use material ui react components
- Because react-virtualized has own Table component I could use it, but react-table has different way of rendering rows and columns, therefore I have to use List component. (react-table separates rows and columns while react-virtualized uses columns directly as children of Table component)
- I saw that react-virtualized works with HOC component called InfiniteLoader, so I should use that as well
- Finally I need my columns to not be messed up just because it has more text (i.e. have dynamic height). So I tried to use CellMeasurer for this.
What I was able to achieve can be seen in this sandbox https://codesandbox.io/s/react-table-infinite-mzkkp?file=/src/MuiTable.js (I cannot provide code here because it is quite large)
So, in general I could make Autosizer, CellMeasurer and List components from react-virtualized to work. I am stuck at inifinite scroll part. I saw the example on official docs, but it seems to be a little bit anti pattern (mutation state directly is not a good thing at all)
So I tried to achieve similar result, however if you could see, my loadMore function fires too early for some reason. It leads to requests being sent on nearly every scroll event.
Any help is much appreciated.
What I tried already:
- Using react-window instead of react-virtualized It works only for simple use cases, and fails with dynamic size of cells.
- Using react-inifnite-scrollcomponent (https://www.npmjs.com/package/react-infinite-scroll-component) It is working for entire page (unable to make "sticky" header, unable to render loading indicators as part of table body, it odes not have any optimization for long lists)
- Using Table component from react-virtualized. I was unable to make it work with react-table (as Table component from react-virtualized seems to render Cells directly as children of Table component. I know it has renderRow function, but it means two separate places while react-table has
<TableRow
{...row.getRowProps({
style
})}
component="div"
>
{row.cells.map((cell) => {
return (
<TableCell {...cell.getCellProps()} component="div">
{cell.render("Cell")}
</TableCell>
);
})}
</TableRow>
Also, it is not clear how to render custom filters this way.