From 715e55cc39955eda9270e332e888d47d86da8885 Mon Sep 17 00:00:00 2001 From: Aleksandra Desmurs-Linczewska Date: Thu, 22 Feb 2024 16:37:06 +0100 Subject: [PATCH 1/4] changed key extractor implementation --- packages/react-native/Libraries/Lists/FlatList.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/react-native/Libraries/Lists/FlatList.js b/packages/react-native/Libraries/Lists/FlatList.js index 3d267cb95988ed..2440c9985f6bd0 100644 --- a/packages/react-native/Libraries/Lists/FlatList.js +++ b/packages/react-native/Libraries/Lists/FlatList.js @@ -566,11 +566,9 @@ class FlatList extends React.PureComponent, void> { 'array with 1-%s columns; instead, received a single item.', numColumns, ); - return items - .map((item, kk) => - keyExtractor(((item: $FlowFixMe): ItemT), index * numColumns + kk), - ) - .join(':'); + // This is not the item key - this is the row key + // Row is static wrapper for items inside and it's key should be static + return `row-index-${index}`; } // $FlowFixMe[incompatible-call] Can't call keyExtractor with an array From 31f9c2fff0203419567ea99716f89377e7733569 Mon Sep 17 00:00:00 2001 From: Aleksandra Desmurs-Linczewska Date: Thu, 22 Feb 2024 16:37:06 +0100 Subject: [PATCH 2/4] Bugfix - FlatList Multicolumn The keyExtractor for multicolumn FlatList was causing all items in the list to remount. This is because the item received by the keyExtractor in case of multicolumn FlatList is a row wrapper - not the item. I changed the return value of keyExtractor for this case in order to stop FlatList items from remounting. --- packages/react-native/Libraries/Lists/FlatList.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/Lists/FlatList.js b/packages/react-native/Libraries/Lists/FlatList.js index 332aab73cd2a03..91ae6d56999d9b 100644 --- a/packages/react-native/Libraries/Lists/FlatList.js +++ b/packages/react-native/Libraries/Lists/FlatList.js @@ -565,9 +565,7 @@ class FlatList extends React.PureComponent, void> { 'array with 1-%s columns; instead, received a single item.', numColumns, ); - // This is not the item key - this is the row key - // Row is static wrapper for items inside and it's key should be static - return `row-index-${index}`; + return `row-index-${index}`; } // $FlowFixMe[incompatible-call] Can't call keyExtractor with an array From d0e7e6dce93a57fdcb1a05219f4f75902e8129a3 Mon Sep 17 00:00:00 2001 From: Aleksandra Desmurs-Linczewska Date: Tue, 27 Feb 2024 13:53:42 +0100 Subject: [PATCH 3/4] Added test case for removing items from multicolumn layout FlatList --- .../examples/FlatList/FlatList-multiColumn.js | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js b/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js index 89e124c6dc33b8..6cc7cf5dd2f829 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js @@ -27,7 +27,14 @@ const { } = require('../../components/ListExampleShared'); const RNTesterPage = require('../../components/RNTesterPage'); const React = require('react'); -const {Alert, FlatList, StyleSheet, Text, View} = require('react-native'); +const { + Alert, + FlatList, + StyleSheet, + Text, + View, + Pressable, +} = require('react-native'); const infoLog = require('react-native/Libraries/Utilities/infoLog'); class MultiColumnExample extends React.PureComponent< @@ -63,6 +70,24 @@ class MultiColumnExample extends React.PureComponent< _setBooleanValue: string => boolean => void = key => value => this.setState({[key]: value}); + _removeThirdItem = () => { + let clonedData = [...this.state.data]; + clonedData.splice(3, 1); + this.setState(state => ({ + ...state, + data: clonedData, + })); + }; + + _removeFifthItem = () => { + let clonedData = [...this.state.data]; + clonedData.splice(5, 1); + this.setState(state => ({ + ...state, + data: clonedData, + })); + }; + render(): React.Node { const filterRegex = new RegExp(String(this.state.filterText), 'i'); const filter = (item: any | Item) => @@ -103,6 +128,14 @@ class MultiColumnExample extends React.PureComponent< this._setBooleanValue('logViewable'), )} + + + Remove item #3 + + + Remove item #5 + + Date: Mon, 22 Jul 2024 12:56:17 +0200 Subject: [PATCH 4/4] updated how the key is built for items in multicolumn layout --- packages/react-native/Libraries/Lists/FlatList.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/Lists/FlatList.js b/packages/react-native/Libraries/Lists/FlatList.js index 91ae6d56999d9b..383f9618751014 100644 --- a/packages/react-native/Libraries/Lists/FlatList.js +++ b/packages/react-native/Libraries/Lists/FlatList.js @@ -638,7 +638,8 @@ class FlatList extends React.PureComponent, void> { const renderProp = (info: RenderItemProps) => { if (cols > 1) { - const {item, index} = info; + const { item, index } = info; + const keyExtractor = this.props.keyExtractor ?? defaultKeyExtractor; invariant( Array.isArray(item), 'Expected array of items with numColumns > 1', @@ -646,6 +647,7 @@ class FlatList extends React.PureComponent, void> { return ( {item.map((it, kk) => { + const key = keyExtractor(it, index * cols + kk); const element = render({ // $FlowFixMe[incompatible-call] item: it, @@ -653,7 +655,7 @@ class FlatList extends React.PureComponent, void> { separators: info.separators, }); return element != null ? ( - {element} + {element} ) : null; })}