-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Example:
The below example adds a log-point inside of VirtualizedList._onScroll
to show when we are responding to scroll messages received from native. This example is intentionally synthetically slow.
We can see from logging that we may continually process scroll messages, long after scrolling has stopped. This is because scroll events are being produced faster than the VirtualizedList
can respond with, and not being coalesced.
Lacks.coalescing.mp4
Steps to repro:
- Create a FlatList/SectionList with
windowSize
equal to 1, and many expensive components to render. E.g.
// Stick this in your item render function to block the JS thread
const fib = n => (n < 2) ? 2 : fib(n-2) + fib(n-1);
fib(30);
- Set
windowSize
to 1 - Place logpoint in
VirtualizedList.onScroll
with `VirtualizedList handled scroll message at (${Date.now()}ms)` or similar - Scroll
Background:
FlatList
through VirtualizedList
listens to the topScroll
native event. React Native provides platform guarantees this is delivered once-per-frame. This is implemented (for UWP and Android) by sending the latest scroll position at the end of a frame.
While this throttles the rate of delivered events, it does not guarantee JS is pumping events fast enough to prevent stale data. If JS rendering exceeds the time of a single native frame, the next render batch will be processing input from a frame behind. This delay is added for every stale message.
By default a single render batch is limited to 10 items. In fast scroll scenarios, each frame can be a different set of items. This means me need to effectively render 10 items per frame from JS to avoid these sorts of delays.