-
Notifications
You must be signed in to change notification settings - Fork 24.5k
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
Prevent VirtualizedList saves items with offsets equal to or below zero and lengths equal to zero #35415
Conversation
Base commit: 81e441a |
Base commit: 81e441a |
PR build artifact for 7018ce7 is ready. |
PR build artifact for 7018ce7 is ready. |
Could you explain more here? If we never mount the items, where does this onLayout callback come from? I would think the mounting would happen in the eventual high pri update? |
Thank you @NickGerleman for the review. That's my understanding of what happens to canceled Low Priority and I interpreted it as the reason for onLayout getting zero values for dimensions. I am open to being corrected, I am still understanding VirtualizedList. Cells of canceled Low Pri never execute onLayout? |
My understanding is that they they should not, since if the low priority update is canceled, the new CellRenderer's the update would create (and add onLayout to) are never added. They are instead first added in the high priority update then. |
Summary
Flatlist on Web has scroll issues when used with expensive items.
I noticed this issue in an App called Expensify. It uses Flatlist for a chat of reports that supports text, images, emojis, and reports as items (and perhaps others that I am not aware of). These items have complex code to support interactions and features on them. As you scroll in the report chat in Web, especially if you scroll fast, you will notice scroll issues like scroll jumps, items appearing and disappearing, or items not showing at all.
Here's Expensify Flatlist Web current state:
Flatlist.Web.Broken.mp4
I recreate a sandbox with expensive items where you can experience the scroll issues I mentioned here.
Steps to reproduce the scroll issues in the sandbox:
I take on the task to improve the scroll experience of react-native-web's Flatlist. I found 3 problems that cause this issue and present their corresponding solution:
$lead_spacer expands scroll artificially when VirtualizedList is mounting new items —> Problem Explanation and Solution in this PR.
VirtualizedList skip items for offset measuring when the user scrolls very fast while new items are mounted and measured —> Problem Explanation and Solution in this PR.
VirtualizedList gets offsets below or equal to zero for items that are not the list's first item —> Problem Explanation and Solution below.
These solutions involve adding or modifying VirtualizedList.js but they improve drastically the scroll experience on Web without causing any regression on Android or iOS.
Also here's Expensify's App after solutions (plus another solution for Inverted VirtualizedLists in react-native-web):
Flatlist.Web.Good.mp4
This PR is the Third Part solution to fix the 'Flatlist with expensive items breaks scroll' issue in react-native-web.
VirtualizedList saves offsets equal to or below zero and lengths equal to zero
As explained in the Second Part PR, a High Priority update cancels every Low Priority update. A canceled Low Priority update will make
onLayout
returns offset and height equal to zero for the items this update pretended to mount. These zero values will be saved in_frames
, associated with the canceled item, even if that item was properly measured on previous updates._frames
object with offsets equal to zero will cause a miss calculation to get items for the virtual area. Because it does not make sense that items in higher positions than the bottom of the list have an offset equal to or below zero.Solution:
Skip the action to save values on our
_frames
and trigger another update if any of the following conditions are met:Changelog
[GENERAL] [FIXED] prevent VirtualizedList saves offsets equal to or below zero and lengths equal to zero
Test Plan
You can test the Flatlist with all solutions applied in this sandbox
Naturally, expensive items will take time to show but you should find no issues on scroll fast.
Also tested in Expensify's App I am working on (see video above)
No problem with iOS
iOS.Flatlist.Compressed.mp4
No problem with Android
Android.Flatlist.mp4
Thank you for reading, let me know what you think!