-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[data grid] Feature: First-party (performant) scroll restoration #15190
Comments
Hey @lauri865 and thanks for opening an issue here. @mui/xgrid thoughts? |
maybe related issue: #15179 |
As an illustration what happens:
It's even worse when the scroll is in the middle of the grid. Then it can render 13+23+3=39 rows (while the viewport fits 8-9) in order to display the restored scroll position.
|
I found the most disgusting way to prevent the first slice form being rendered 🤡: const unsubscribe = apiRef.current.subscribeEvent("stateChange", (state) => {
state.virtualization.renderContext = gridState.renderContext;
}); (need to unsubscribe from the event when the grid is ready / after restoring scroll) You will probably get fired if you use it at work though, but it's the only option that gets rid of unnecessary rendering. |
Summary
We implement most of our Datagrids while persisting state between navigations for better UX. It's all good implemented in userland, and no complaints there in general.
However, restoring scroll is extremely painful in userland, and it's impossible to achieve a performant outcome there, because the initial renderContext is flushSynced, and there's no way to override that. So you end up with reflows and unnecessary component renders (even if they don't end up in the DOM, e.g. canvas elements end up still be drawn and have to be trashed if they don't end up in the viewport) on remounting the grid.
Examples
What works but is slow / subject to reflows / unnecessary computations:
Slightly more performant, but less widely supported option (based on heuristics rather than explictly waiting for the virtualScroll to enter the DOM):
Even more performant option (almost there, but could be better):
Almost as snappy as without scroll restoration, but expensive components are still called and flushSync needs to wait for another flushSync to complete from what I understand, so we still lose a frame or a few and end up with higher CPU use.
Motivation
The source of the issue seems to be – the following call to
updateRenderContext
cannot be intercepted or overridden:https://github.com/mui/mui-x/blob/f613377c4740cb7ebda19d4b3a81cf27be8e0a01/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx#L580C3-L591C6
FlushSynced:
mui-x/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx
Lines 279 to 282 in f613377
Maybe a stopgap solution could be if
scrollPositionChange
could prevent the default behaviour (e.g. could prevent the first event and first invocation ofupdateRenderContext
).Restoring scroll is difficult in userland, subject to performance woes and regardless of the approach, ends up in spaghetti code that may not work in future versions.
Related: #5071 and #6411
Opened a new issue as these discussions are stale and based on old versions.
Search keywords: restore scroll
The text was updated successfully, but these errors were encountered: