mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
VirtualizedList optimization - memoize FlatList._renderer
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 (fixed in D35062323 (https://github.com/facebook/react-native/commit/adb2962fee968d7ae20ec32a55dc69e4ebb3ce12)) - FlatList recreates renderItem/ListItemComponent in FlatList._renderer (addressed in this diff) Changelog: [Internal] - VirtualizedList optimization - memoize FlatList._renderer Reviewed By: ryancat Differential Revision: D35067472 fbshipit-source-id: 124629d94821f35b8943730839fbe72f547e80fd
This commit is contained in:
committed by
Facebook GitHub Bot
parent
adb2962fee
commit
c231d5e371
@@ -727,6 +727,7 @@ rn_library(
|
||||
"//xplat/js:node_modules__base64_19js",
|
||||
"//xplat/js:node_modules__event_19target_19shim",
|
||||
"//xplat/js:node_modules__invariant",
|
||||
"//xplat/js:node_modules__memoize_19one",
|
||||
"//xplat/js:node_modules__nullthrows",
|
||||
"//xplat/js:node_modules__pretty_19format",
|
||||
"//xplat/js:node_modules__promise",
|
||||
|
||||
@@ -26,6 +26,7 @@ import type {
|
||||
} from './ViewabilityHelper';
|
||||
import type {RenderItemType, RenderItemProps} from './VirtualizedList';
|
||||
import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils';
|
||||
import memoizeOne from 'memoize-one';
|
||||
|
||||
type RequiredProps<ItemT> = {|
|
||||
/**
|
||||
@@ -141,6 +142,10 @@ type OptionalProps<ItemT> = {|
|
||||
* See `ScrollView` for flow type and further documentation.
|
||||
*/
|
||||
fadingEdgeLength?: ?number,
|
||||
/**
|
||||
* Enable an optimization to memoize the item renderer to prevent unnecessary rerenders.
|
||||
*/
|
||||
strictMode?: boolean,
|
||||
|};
|
||||
|
||||
/**
|
||||
@@ -578,9 +583,14 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
|
||||
};
|
||||
}
|
||||
|
||||
_renderer = () => {
|
||||
const {ListItemComponent, renderItem, columnWrapperStyle} = this.props;
|
||||
const numColumns = numColumnsOrDefault(this.props.numColumns);
|
||||
_renderer = (
|
||||
ListItemComponent: ?(React.ComponentType<any> | React.Element<any>),
|
||||
renderItem: ?RenderItemType<ItemT>,
|
||||
columnWrapperStyle: ?ViewStyleProp,
|
||||
numColumns: ?number,
|
||||
extraData: ?any,
|
||||
) => {
|
||||
const cols = numColumnsOrDefault(numColumns);
|
||||
|
||||
let virtualizedListRenderKey = ListItemComponent
|
||||
? 'ListItemComponent'
|
||||
@@ -605,7 +615,7 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
|
||||
* This comment suppresses an error found when Flow v0.111 was deployed.
|
||||
* To see the error, delete this comment and run Flow. */
|
||||
[virtualizedListRenderKey]: (info: RenderItemProps<ItemT>) => {
|
||||
if (numColumns > 1) {
|
||||
if (cols > 1) {
|
||||
const {item, index} = info;
|
||||
invariant(
|
||||
Array.isArray(item),
|
||||
@@ -616,7 +626,7 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
|
||||
{item.map((it, kk) => {
|
||||
const element = renderer({
|
||||
item: it,
|
||||
index: index * numColumns + kk,
|
||||
index: index * cols + kk,
|
||||
separators: info.separators,
|
||||
});
|
||||
return element != null ? (
|
||||
@@ -632,14 +642,19 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
|
||||
};
|
||||
};
|
||||
|
||||
_memoizedRenderer = memoizeOne(this._renderer);
|
||||
|
||||
render(): React.Node {
|
||||
const {
|
||||
numColumns,
|
||||
columnWrapperStyle,
|
||||
removeClippedSubviews: _removeClippedSubviews,
|
||||
strictMode = false,
|
||||
...restProps
|
||||
} = this.props;
|
||||
|
||||
const renderer = strictMode ? this._memoizedRenderer : this._renderer;
|
||||
|
||||
return (
|
||||
<VirtualizedList
|
||||
{...restProps}
|
||||
@@ -651,7 +666,13 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
|
||||
removeClippedSubviews={removeClippedSubviewsOrDefault(
|
||||
_removeClippedSubviews,
|
||||
)}
|
||||
{...this._renderer()}
|
||||
{...renderer(
|
||||
this.props.ListItemComponent,
|
||||
this.props.renderItem,
|
||||
columnWrapperStyle,
|
||||
numColumns,
|
||||
this.props.extraData,
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
"hermes-engine": "~0.11.0",
|
||||
"invariant": "^2.2.4",
|
||||
"jsc-android": "^250230.2.1",
|
||||
"memoize-one": "^5.0.0",
|
||||
"metro-react-native-babel-transformer": "0.69.1",
|
||||
"metro-runtime": "0.69.1",
|
||||
"metro-source-map": "0.69.1",
|
||||
|
||||
@@ -4926,6 +4926,11 @@ map-visit@^1.0.0:
|
||||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
memoize-one@^5.0.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
|
||||
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
|
||||
Reference in New Issue
Block a user