Skip to content

Commit 305c534

Browse files
committed
Refactor recycling manager to be faster and more efficient
1 parent f098e61 commit 305c534

17 files changed

+892
-566
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const MyList = () => {
7474
```
7575

7676
- `onStartReachedThreshold`: How far from the start the top edge of the list must be to trigger `onStartReached`.
77-
- `disableRecycling`: If true, the FlashList will not recycle items.
77+
- `maxItemsInRecyclePool`: Maximum number of items in the recycle pool (Not required unless the number of item types is huge).
7878
- `style`: Style for the FlashList's parent container. We highly recommend not adding padding which can impact the size of the ScrollView inside. We operate on the assumption that the size of parent view and ScrollView is the same. In most cases, `contentContainerStyle` should be enough so avoid using this.
7979
- `maintainVisibleContentPosition`: Configuration for maintaining scroll position when content changes:
8080
- `disabled`: Set to true to disable this feature (enabled by default).

documentation/docs/fundamentals/usage.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,13 @@ Enable masonry layout for grid-like interfaces with varying item heights. When u
278278
/>
279279
```
280280

281+
### `maxItemsInRecyclePool`
282+
283+
Maximum number of items in the recycle pool. These are the items that are cached in the recycle pool when they are scrolled off the screen. Unless you have a huge number of item types, you shouldn't need to set this.
284+
285+
Setting this to 0, will disable the recycle pool and items will unmount once they are scrolled off the screen.
286+
There's no limit by default.
287+
281288
### `numColumns`
282289

283290
Multiple columns can only be rendered with `horizontal={false}` and will zig-zag like a `flexWrap` layout. Items should all be the same height - masonry layouts are not supported.

fixture/react-native/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
*/
44

55
import { AppRegistry, I18nManager } from "react-native";
6+
import { enableNewCore } from "@shopify/flash-list/dist/enableNewCore";
67

78
import App from "./src/App";
89
import { name as appName } from "./app.json";
910

11+
enableNewCore(true);
12+
1013
I18nManager.forceRTL(false);
1114

1215
AppRegistry.registerComponent(appName, () => App);

fixture/react-native/src/App.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,11 @@
88

99
import "react-native-gesture-handler";
1010
import React from "react";
11-
import { Platform, UIManager } from "react-native";
1211

1312
import { DebugContextProvider } from "./Debug";
1413
import NavigationTree from "./NavigationTree";
1514

1615
const App = () => {
17-
if (Platform.OS === "android") {
18-
if (UIManager.setLayoutAnimationEnabledExperimental) {
19-
UIManager.setLayoutAnimationEnabledExperimental(true);
20-
}
21-
}
22-
2316
return (
2417
<DebugContextProvider>
2518
<NavigationTree />

fixture/react-native/src/List.tsx

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
Use this component inside your React Native Application.
33
A scrollable list with different item type
44
*/
5-
import React, { useRef, useState } from "react";
6-
import {
7-
View,
8-
Text,
9-
Pressable,
10-
LayoutAnimation,
11-
StyleSheet,
12-
} from "react-native";
13-
import { FlashList, RecyclerView } from "@shopify/flash-list";
5+
import React, { useCallback, useEffect, useRef, useState } from "react";
6+
import { View, Text, Pressable, StyleSheet } from "react-native";
7+
import { RecyclerView, FlashListRef } from "@shopify/flash-list";
8+
import Animated, {
9+
FadeIn,
10+
FadeOut,
11+
LinearTransition,
12+
} from "react-native-reanimated";
1413

1514
const generateArray = (size: number) => {
1615
const arr = new Array(size);
@@ -22,41 +21,44 @@ const generateArray = (size: number) => {
2221

2322
const List = () => {
2423
const [refreshing, setRefreshing] = useState(false);
25-
const [data, setData] = useState(generateArray(100));
24+
const [data, setData] = useState(() => generateArray(100));
2625

27-
const list = useRef<FlashList<number> | null>(null);
26+
const list = useRef<FlashListRef<number> | null>(null);
2827

29-
const removeItem = (item: number) => {
30-
setData(
31-
data.filter((dataItem) => {
32-
return dataItem !== item;
33-
})
34-
);
28+
const removeItem = useCallback((item: number) => {
3529
list.current?.prepareForLayoutAnimationRender();
36-
// after removing the item, we start animation
37-
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
38-
};
3930

40-
const renderItem = ({ item }: { item: number }) => {
41-
const backgroundColor = item % 2 === 0 ? "#00a1f1" : "#ffbb00";
42-
return (
43-
<Pressable
44-
onPress={() => {
45-
removeItem(item);
46-
}}
47-
>
48-
<View
49-
style={{
50-
...styles.container,
51-
backgroundColor: item > 97 ? "red" : backgroundColor,
52-
height: item % 2 === 0 ? 100 : 200,
31+
setData((prevData) => {
32+
return prevData.filter((dataItem) => {
33+
return dataItem !== item;
34+
});
35+
});
36+
}, []);
37+
38+
const renderItem = useCallback(
39+
({ item }: { item: number }) => {
40+
const backgroundColor = item % 2 === 0 ? "#00a1f1" : "#ffbb00";
41+
console.log("renderItem", item);
42+
return (
43+
<Pressable
44+
onPress={() => {
45+
removeItem(item);
5346
}}
5447
>
55-
<Text>Cell Id: {item}</Text>
56-
</View>
57-
</Pressable>
58-
);
59-
};
48+
<View
49+
style={{
50+
...styles.container,
51+
backgroundColor: item > 97 ? "red" : backgroundColor,
52+
height: item % 2 === 0 ? 100 : 200,
53+
}}
54+
>
55+
<Text>Cell Id: {item}</Text>
56+
</View>
57+
</Pressable>
58+
);
59+
},
60+
[removeItem]
61+
);
6062

6163
return (
6264
<RecyclerView
@@ -68,6 +70,7 @@ const List = () => {
6870
setRefreshing(false);
6971
}, 2000);
7072
}}
73+
CellRendererComponent={CellRenderer}
7174
keyExtractor={(item: number) => {
7275
return item.toString();
7376
}}
@@ -82,6 +85,16 @@ const List = () => {
8285

8386
export default List;
8487

88+
const CellRenderer = (props: any) => {
89+
return (
90+
<Animated.View
91+
{...props}
92+
layout={LinearTransition}
93+
entering={FadeIn}
94+
exiting={FadeOut}
95+
/>
96+
);
97+
};
8598
const styles = StyleSheet.create({
8699
container: {
87100
justifyContent: "space-around",

fixture/web/Grid.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export function Grid() {
7676
contentContainerStyle={contentContainerStyle}
7777
// maintainVisibleContentPosition={{}}
7878
initialScrollIndex={25}
79-
//overrideItemLayout={overrideItemLayout}
79+
// overrideItemLayout={overrideItemLayout}
8080
renderItem={renderItem}
8181
keyExtractor={keyExtractor}
8282
/>

src/FlashListProps.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,15 @@ export interface FlashListProps<TItem>
340340
*/
341341
disableAutoLayout?: boolean;
342342

343+
/**
344+
* New arch only
345+
* Maximum number of items in the recycle pool. These are the items that are cached in the recycle pool when they are scrolled off the screen.
346+
* Unless you have a huge number of item types, you shouldn't need to set this.
347+
* Setting this to 0, will disable the recycle pool and items will unmount once they are scrolled off the screen.
348+
* There's no limit by default.
349+
*/
350+
maxItemsInRecyclePool?: number;
351+
343352
/**
344353
* New arch only
345354
* Enable masonry layout.
@@ -366,12 +375,6 @@ export interface FlashListProps<TItem>
366375
*/
367376
onStartReachedThreshold?: FlashListProps<TItem>["onEndReachedThreshold"];
368377

369-
/**
370-
* New arch only
371-
* If true, the RecyclerView will not recycle items.
372-
*/
373-
disableRecycling?: boolean;
374-
375378
/**
376379
* New arch only
377380
* Style for the RecyclerView's parent container.

0 commit comments

Comments
 (0)