4

I have implemented an Infinite scrolling table with react-window (based on #60) and material UI.

The table seems to be fulfilling the main objective but there are few issues with it -

  1. header is not sticking on the top in spite of having styles in place (stickyHeader prop).
  2. header is flashing/flickering while scrolling quickly towards up direction. [Steps to reproduce - scroll 50% down then do fast scroll up and observe the header movement ].

Here's the codesandbox example - https://codesandbox.io/s/react-window-with-table-elements-forked-huti6?file=/src/index.tsx:514-542

10 Rep
  • 2,217
  • 7
  • 19
  • 33
Dev AKS
  • 512
  • 1
  • 5
  • 17
  • The flickering is a feature, not a bug...... What's happening is `react-window-infinite-loader` is displaying only the data currently visible in the viewport, in order to speed up load times. As you scroll up, new data is loaded, and the old data is removed, but if you scroll very fast it can't keep up. Take a look at what's happening inside `.MuiTableBody-root` – Eliezer Berlin Sep 30 '20 at 17:56
  • @EliezerBerlin what you said is correct, there are lots of add-delete in the TBody section so flickering there is fine but there are no changes in the header section so it supposed to be freeze, right? – Dev AKS Oct 01 '20 at 07:32
  • Again, it's from `react-window-infinite-loader`. The table moves around using position:absolute and `top`. The real cause of the flickering is that the `top` attribute on the `table.MuiTable-root` isn't fast enough to keep up with your scrolling. – Eliezer Berlin Oct 01 '20 at 08:17
  • Though you might also want to add the css: `table-layout:fixed;` to your table so that the width of the header isn't determined by the width of the *currently visible content*. – Eliezer Berlin Oct 01 '20 at 08:19
  • Tried `table-layout: fixed;`, didn't see any difference. – Dev AKS Oct 01 '20 at 11:02
  • Well, in the demo, the width of every column is identical, so there's not much difference. But when you get to a real site, your data is going to have different widths, and that might cause the width of columns to change if you don't use table-layout:fixed. (It's not going to affect the flickering.) – Eliezer Berlin Oct 01 '20 at 14:01
  • Understood, that's a good point. Thanks :) – Dev AKS Oct 02 '20 at 06:41

3 Answers3

0

Use default value for TableContainer overflow-x and the sticky header should work

import { makeStyles } from '@material-ui/core/styles'

const useStyles = makeStyles({
  tableContainer: {
    overflowX: "initial"
  }
})

function Inner({ children, ...rest }, ref) {
  const { header, footer, top } = useContext(VirtualTableContext)
  const classes = useStyles();
  return (
    <TableContainer classes={{root: classes.tableContainer}} {...rest} ref={ref}>
    ...

Edit React-Window with table elements (forked)

95faf8e76605e973
  • 13,643
  • 3
  • 24
  • 51
0

As an alternative to your implementation, the Material UI docs have a working example of a virtualized table which achieves what you're looking for using react-virtualized. That is, the header is sticky and there is no flashing/flickering of the header during scroll.

Below is a codesandbox containing a working example to reflect your desired layout.

 Material demo (forked)

Tejogol
  • 670
  • 8
  • 24
  • react-window is a complete rewrite of react-virtualized and It is much lighter and faster than react-virtualized. The main problem here is due to the infinite loader, It is causing header flickering so changing the library won't make any difference. There won't be a header issue in the plain virtual table by react-window. – Dev AKS Sep 28 '20 at 08:50
  • @DevAKS Yes, agreed that there won't be a header issue if you use the plain virtual table by react-window. In fact, there is a nice [example](https://codesandbox.io/s/0mk3qwpl4l) of such a solution available. Given that the full functionality of react-window-infinite-loader is not implemented in your solution (i.e. you do not simulate the loading of remote data), why do you need a solution that includes react-window-infinite-loader? – Tejogol Sep 28 '20 at 14:32
0

First about the react-window: The Scollbars in the react-window are for the outercontainer not for InnerContainer. Now don't try to replace the outer container itself, unless you want to handle everything yourself. All the scroll events a few more things are attached to the outercontainer.

Think of it like outer container decides/takes the size and the larger inner container gets scrolled inside it.

Now looking at your case I assume you are trying to make the table behave like any other grid where headers are fixed and content is scrolled if it's getting overflow. your table header is way lower in the element hierarchy than the inner container, so no way you can write any simple css (or js logic) to achieve in current hierarchy.

that's why even though you have set the stickyheader for the MaterialUI table, it won't stick. Cause your whole table (MaterialUI table) is getting scrolled inside the outer container of react-window.

I would suggest you to move your table header outside of the react-window and only place the rows in the react-widow. that's the way it's suppose to behave (i.e. react window treats everything in it as scrollable content). See one of the presentation below:

ReactWindow

A little tip on redesigning of your table (guess the alignment can be improved by additional css)

header outside of reactwindow

Kylo Ren
  • 8,551
  • 6
  • 41
  • 66
  • Thanks for your detailed explanation. We cannot put `react-window` on rows only as it is a violation of material UI rules, you cannot add extra div inside TableBody. Also, I tried your suggested changes, It is not working and It is giving warning (`Warning: validateDOMNesting(...): cannot appear as a child of
    .`)
    – Dev AKS Oct 03 '20 at 09:25
  • @DevAKS so you are just concerned about the rule of MaterialUI not react-window. you have out the materil UI table at the wrong hierarchy level to begin with. You can design your component as your need. The idea is, don't think the header as html table header (th) think of it as normal header (collection of DIVs). which is also the cause of your error, i.e. table header outside of a table. just make it outside of the react-window. I suppose the table footer will have same issue. more precisely only TableBody should be inside the react-window. – Kylo Ren Oct 04 '20 at 04:23
  • @DevAKS btw equally curious to know which rule are you breaking by designing something like {react-window}
    – Kylo Ren Oct 04 '20 at 04:49
  • Well, I am concerned about the rules as a violation of these rules generates a warning and I can't have such code in production that generates a warning. – Dev AKS Oct 04 '20 at 07:03
  • Also, I have provided codesandbox link there you can check the console, it is generating zero warning/errors. – Dev AKS Oct 04 '20 at 07:05
  • @DevAKS the warning is about the is being used without the table. I was just giving you a tip on design. in my view, you should just create {header} {body} and {footer} inside the VirtualTable compoent and just remove the inner component completely. and in the VirtualTable compoent the react-window should be used to wrap the {tablebody}. – Kylo Ren Oct 05 '20 at 05:32