mirror of
https://github.com/status-im/react-native.git
synced 2025-01-28 02:04:55 +00:00
Prevent unintended VirtualizedList high priority rendering
Summary: VirtualizedList sets high priority rendering when scrolled to the top of a list even if the bottom of the rendered list is still far away and there's nothing further to render above. This causes severe non-responsiveness while dozens of items are waiting to be rendered and user inputs can't get through. The fix is simply to not consider it high priority to render more items when we reach the top and the first item has already been rendered, or when we reach the bottom and the last item has been rendered. The code change just splits the two cases (hitting the top and bottom) instead of combining them into one. I wrote a small application that switches between two FlatLists. Demo of the original VirtualizedList <img src="https://user-images.githubusercontent.com/3090032/39456709-2c87069e-4d1b-11e8-8535-5bda6d59400c.gif" width="270" height="480"> I'm clicking pretty often on the button, but you can see that it only switches lists a split second after the rendering is all done because the javascript thread was being blocked. Demo of the fixed VirtualizedList <img src="https://user-images.githubusercontent.com/3090032/39456844-00312448-4d1c-11e8-805f-cbe17aa3f95e.gif" width="270" height="480"> You can see this one is significantly more responsive than the previous one. The source code for the demo application is available [here](https://gist.github.com/jabbawookiees/ba93a4e7b4f9b8f3acbc157e4fd04877) [ GENERAL ] [ ENHANCEMENT ] [ Libraries/Lists/VirtualizedList.js ] - Prevent high priority rendering at the top or bottom of a list. Closes https://github.com/facebook/react-native/pull/19081 Differential Revision: D7933994 Pulled By: sahrens fbshipit-source-id: 13c9f73baeb3487620b720854a753287ac0aa1fa
This commit is contained in:
parent
e708010d18
commit
c18cf5bd4a
@ -1344,19 +1344,23 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
||||
const {offset, visibleLength, velocity} = this._scrollMetrics;
|
||||
const itemCount = this.props.getItemCount(this.props.data);
|
||||
let hiPri = false;
|
||||
if (first > 0 || last < itemCount - 1) {
|
||||
const scrollingThreshold =
|
||||
/* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.63 was deployed. To see the error delete
|
||||
* this comment and run Flow. */
|
||||
this.props.onEndReachedThreshold * visibleLength / 2;
|
||||
// Mark as high priority if we're close to the start of the first item
|
||||
// But only if there are items before the first rendered item
|
||||
if (first > 0) {
|
||||
const distTop = offset - this._getFrameMetricsApprox(first).offset;
|
||||
hiPri = hiPri || distTop < 0 || (velocity < -2 && distTop < scrollingThreshold);
|
||||
}
|
||||
// Mark as high priority if we're close to the end of the last item
|
||||
// But only if there are items after the last rendered item
|
||||
if (last < itemCount - 1) {
|
||||
const distBottom =
|
||||
this._getFrameMetricsApprox(last).offset - (offset + visibleLength);
|
||||
const scrollingThreshold =
|
||||
/* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.63 was deployed. To see the error delete
|
||||
* this comment and run Flow. */
|
||||
this.props.onEndReachedThreshold * visibleLength / 2;
|
||||
hiPri =
|
||||
Math.min(distTop, distBottom) < 0 ||
|
||||
(velocity < -2 && distTop < scrollingThreshold) ||
|
||||
(velocity > 2 && distBottom < scrollingThreshold);
|
||||
hiPri = hiPri || distBottom < 0 || (velocity > 2 && distBottom < scrollingThreshold);
|
||||
}
|
||||
// Only trigger high-priority updates if we've actually rendered cells,
|
||||
// and with that size estimate, accurately compute how many cells we should render.
|
||||
|
Loading…
x
Reference in New Issue
Block a user