From adb2962fee968d7ae20ec32a55dc69e4ebb3ce12 Mon Sep 17 00:00:00 2001 From: Genki Kondo Date: Thu, 24 Mar 2022 10:05:14 -0700 Subject: [PATCH] VirtualizedList optimization - refactor CellRenderer props to eliminate parentProps Summary: Problem: All CellRenderers rerender every time the containing VirtualizedList is rerendered. This is due to the following: - Lambda is created for each CellRenderer's onLayout prop on every VirtualizedList render (fixed in D35061321 (https://github.com/facebook/react-native/commit/19cf70266eb8ca151aa0cc46ac4c09cb987b2ceb)) - CellRenderer's parentProps prop changes on every VirtualizedList render (addressed in this diff) - FlatList recreates renderItem/ListItemComponent in FlatList._renderer Changelog: [Internal] - VirtualizedList optimization - refactor CellRenderer props to eliminate parentProps Reviewed By: javache Differential Revision: D35062323 fbshipit-source-id: 705c2f7c6c482b7813efdfdac7019a94594de590 --- Libraries/Lists/VirtualizedList.js | 50 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 728a4b06582..0a02fb1ef15 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -797,12 +797,17 @@ class VirtualizedList extends React.PureComponent { const { CellRendererComponent, ItemSeparatorComponent, + ListHeaderComponent, + ListItemComponent, data, + debug, getItem, getItemCount, + getItemLayout, horizontal, + renderItem, } = this.props; - const stickyOffset = this.props.ListHeaderComponent ? 1 : 0; + const stickyOffset = ListHeaderComponent ? 1 : 0; const end = getItemCount(data) - 1; let prevCellKey; last = Math.min(end, last); @@ -817,8 +822,11 @@ class VirtualizedList extends React.PureComponent { { onCellLayout={this._onCellLayout} onUpdateSeparators={this._onUpdateSeparators} onUnmount={this._onCellUnmount} - parentProps={this.props} ref={ref => { this._cellRefs[key] = ref; }} + renderItem={renderItem} />, ); prevCellKey = key; @@ -1887,8 +1895,19 @@ type CellRendererProps = { ItemSeparatorComponent: ?React.ComponentType< any | {highlighted: boolean, leadingItem: ?Item}, >, + ListItemComponent?: ?(React.ComponentType | React.Element), cellKey: string, + debug?: ?boolean, fillRateHelper: FillRateHelper, + getItemLayout?: ( + data: any, + index: number, + ) => { + length: number, + offset: number, + index: number, + ... + }, horizontal: ?boolean, index: number, inversionStyle: ViewStyleProp, @@ -1897,22 +1916,8 @@ type CellRendererProps = { onCellLayout: (event: Object, cellKey: string, index: number) => void, onUnmount: (cellKey: string) => void, onUpdateSeparators: (cellKeys: Array, props: Object) => void, - parentProps: { - // e.g. height, y, - getItemLayout?: ( - data: any, - index: number, - ) => { - length: number, - offset: number, - index: number, - ... - }, - renderItem?: ?RenderItemType, - ListItemComponent?: ?(React.ComponentType | React.Element), - ... - }, prevCellKey: ?string, + renderItem?: ?RenderItemType, ... }; @@ -2030,14 +2035,16 @@ class CellRenderer extends React.Component< const { CellRendererComponent, ItemSeparatorComponent, + ListItemComponent, + debug, fillRateHelper, + getItemLayout, horizontal, item, index, inversionStyle, - parentProps, + renderItem, } = this.props; - const {renderItem, getItemLayout, ListItemComponent} = parentProps; const element = this._renderElement( renderItem, ListItemComponent, @@ -2046,10 +2053,7 @@ class CellRenderer extends React.Component< ); const onLayout = - /* $FlowFixMe[prop-missing] (>=0.68.0 site=react_native_fb) This comment - * suppresses an error found when Flow v0.68 was deployed. To see the - * error delete this comment and run Flow. */ - (getItemLayout && !parentProps.debug && !fillRateHelper.enabled()) || + (getItemLayout && !debug && !fillRateHelper.enabled()) || !this.props.onCellLayout ? undefined : this._onLayout;