From aaa0b7066fd299783fd4061cd53c5465d06dfd23 Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Thu, 20 Apr 2023 12:15:44 -0300 Subject: [PATCH 1/8] feat: shopify/flash-list support --- package.json | 3 ++- src/helpers.tsx | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bc562674..34e92903 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,8 @@ "react": "*", "react-native": "*", "react-native-pager-view": "*", - "react-native-reanimated": ">=2.15.0" + "react-native-reanimated": ">=2.15.0", + "@shopify/flash-list": ">=1.0.0" }, "peerDependenciesMeta": { "@shopify/flash-list": { diff --git a/src/helpers.tsx b/src/helpers.tsx index 4a6b572f..7a1cde49 100644 --- a/src/helpers.tsx +++ b/src/helpers.tsx @@ -1,3 +1,4 @@ +import { FlashList } from '@shopify/flash-list' import { FlatList, Platform, SectionList, I18nManager } from 'react-native' import Animated, { scrollTo } from 'react-native-reanimated' @@ -28,3 +29,5 @@ export function scrollToImpl( scrollTo(ref, x, y, animated) } + +export const AnimatedFlashList = Animated.createAnimatedComponent(FlashList) From 02a71d955827f1ea630228d5dd34b6564b2644a9 Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Thu, 20 Apr 2023 14:18:55 -0300 Subject: [PATCH 2/8] feat: added example for FlashList --- example/src/AnimatedHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/src/AnimatedHeader.tsx b/example/src/AnimatedHeader.tsx index a16a9d58..49d40f8f 100644 --- a/example/src/AnimatedHeader.tsx +++ b/example/src/AnimatedHeader.tsx @@ -8,7 +8,7 @@ import Animated, { } from 'react-native-reanimated' import { useCurrentTabScrollY } from '../../src/hooks' -import ExampleComponent from './Shared/ExampleComponent' +import ExampleComponent from './Shared/ExampleComponentFlashList' import ReText from './Shared/ReText' import { ExampleComponentType } from './types' From b95ea04e7f5118c25d2b31fe81678233f204dfae Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Thu, 20 Apr 2023 15:29:10 -0300 Subject: [PATCH 3/8] feat: fixed issue realted to scrollTo in Reanimated --- example/ios/Podfile.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index cd0ea245..a5b63460 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -411,7 +411,7 @@ DEPENDENCIES: - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - - "RNFlashList (from `../../node_modules/@shopify/flash-list`)" + - "RNFlashList (from `../node_modules/@shopify/flash-list`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNReanimated (from `../node_modules/react-native-reanimated`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -504,7 +504,7 @@ EXTERNAL SOURCES: ReactCommon: :path: "../node_modules/react-native/ReactCommon" RNFlashList: - :path: "../../node_modules/@shopify/flash-list" + :path: "../node_modules/@shopify/flash-list" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNReanimated: @@ -513,8 +513,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - boost: 57d2868c099736d80fcd648bf211b4431e51a558 - DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 + boost: a7c83b31436843459a1961bfd74b96033dc77234 + DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 EXApplication: d8f53a7eee90a870a75656280e8d4b85726ea903 EXConstants: f348da07e21b23d2b085e270d7b74f282df1a7d9 EXFileSystem: 844e86ca9b5375486ecc4ef06d3838d5597d895d @@ -526,7 +526,7 @@ SPEC CHECKSUMS: FBLazyVector: a83ceaa8a8581003a623facdb3c44f6d4f342ac5 FBReactNativeSpec: 85eee79837cb797ab6176f0243a2b40511c09158 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 - glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b + glog: 476ee3e89abb49e07f822b48323c51c57124b572 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: 5c6fd63b03abb06947d348dadac51c93e3485bd8 RCTTypeSafety: 1c66daedd66f674e39ce9f40782f0d490c78b175 @@ -562,4 +562,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 4a1d4df08804ad081db13b6bea02bebbb098497a -COCOAPODS: 1.12.1 +COCOAPODS: 1.11.3 From 6ebbdb19674801d117bb587a1383dd593a706da0 Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Thu, 20 Apr 2023 15:33:08 -0300 Subject: [PATCH 4/8] chore: created example to showcase flashlist --- example/src/AnimatedHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/src/AnimatedHeader.tsx b/example/src/AnimatedHeader.tsx index 49d40f8f..a16a9d58 100644 --- a/example/src/AnimatedHeader.tsx +++ b/example/src/AnimatedHeader.tsx @@ -8,7 +8,7 @@ import Animated, { } from 'react-native-reanimated' import { useCurrentTabScrollY } from '../../src/hooks' -import ExampleComponent from './Shared/ExampleComponentFlashList' +import ExampleComponent from './Shared/ExampleComponent' import ReText from './Shared/ReText' import { ExampleComponentType } from './types' From e751a3afef455a5edf9d275b67fd3e5ce3a23369 Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Fri, 21 Apr 2023 11:35:26 -0300 Subject: [PATCH 5/8] fix: updated dependencies to keep flashlist as optional --- example/ios/Podfile.lock | 6 ------ src/FlashList.tsx | 13 +++++++++++++ src/helpers.tsx | 3 --- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a5b63460..b2b3c31e 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -335,8 +335,6 @@ PODS: - React-jsi (= 0.71.6) - React-logger (= 0.71.6) - React-perflogger (= 0.71.6) - - RNFlashList (1.4.2): - - React-Core - RNGestureHandler (2.9.0): - React-Core - RNReanimated (2.14.4): @@ -411,7 +409,6 @@ DEPENDENCIES: - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - - "RNFlashList (from `../node_modules/@shopify/flash-list`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNReanimated (from `../node_modules/react-native-reanimated`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -503,8 +500,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" ReactCommon: :path: "../node_modules/react-native/ReactCommon" - RNFlashList: - :path: "../node_modules/@shopify/flash-list" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNReanimated: @@ -555,7 +550,6 @@ SPEC CHECKSUMS: React-RCTVibration: 73d201599a64ea14b4e0b8f91b64970979fd92e6 React-runtimeexecutor: 8692ac548bec648fa121980ccb4304afd136d584 ReactCommon: e1067159764444e5db7c14e294d5cd79fb159c59 - RNFlashList: 7fbca4fc075484a9426f1610d648dbea2de94eb0 RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128 Yoga: ba09b6b11e6139e3df8229238aa794205ca6a02a diff --git a/src/FlashList.tsx b/src/FlashList.tsx index 011ad255..a4229be8 100644 --- a/src/FlashList.tsx +++ b/src/FlashList.tsx @@ -17,6 +17,19 @@ import { useUpdateScrollViewContentSize, } from './hooks' +// Load FlashList dynamically or print a friendly error message +let AnimatedFlashList: React.ComponentClass> +try { + const flashListModule = require('@shopify/flash-list') + AnimatedFlashList = (Animated.createAnimatedComponent( + flashListModule.FlashList + ) as unknown) as React.ComponentClass> +} catch (error) { + console.error( + 'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.' + ) +} + /** * Used as a memo to prevent rerendering too often when the context changes. * See: https://github.com/facebook/react/issues/15156#issuecomment-474590693 diff --git a/src/helpers.tsx b/src/helpers.tsx index 7a1cde49..4a6b572f 100644 --- a/src/helpers.tsx +++ b/src/helpers.tsx @@ -1,4 +1,3 @@ -import { FlashList } from '@shopify/flash-list' import { FlatList, Platform, SectionList, I18nManager } from 'react-native' import Animated, { scrollTo } from 'react-native-reanimated' @@ -29,5 +28,3 @@ export function scrollToImpl( scrollTo(ref, x, y, animated) } - -export const AnimatedFlashList = Animated.createAnimatedComponent(FlashList) From ef05002aaa90e796baeb170828a65f276d045230 Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Fri, 21 Apr 2023 11:47:28 -0300 Subject: [PATCH 6/8] fix: dependency being required when using specific list implementation --- example/ios/Podfile.lock | 6 ++++++ src/FlashList.tsx | 13 ------------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index b2b3c31e..a5b63460 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -335,6 +335,8 @@ PODS: - React-jsi (= 0.71.6) - React-logger (= 0.71.6) - React-perflogger (= 0.71.6) + - RNFlashList (1.4.2): + - React-Core - RNGestureHandler (2.9.0): - React-Core - RNReanimated (2.14.4): @@ -409,6 +411,7 @@ DEPENDENCIES: - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNFlashList (from `../node_modules/@shopify/flash-list`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNReanimated (from `../node_modules/react-native-reanimated`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -500,6 +503,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RNFlashList: + :path: "../node_modules/@shopify/flash-list" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNReanimated: @@ -550,6 +555,7 @@ SPEC CHECKSUMS: React-RCTVibration: 73d201599a64ea14b4e0b8f91b64970979fd92e6 React-runtimeexecutor: 8692ac548bec648fa121980ccb4304afd136d584 ReactCommon: e1067159764444e5db7c14e294d5cd79fb159c59 + RNFlashList: 7fbca4fc075484a9426f1610d648dbea2de94eb0 RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128 Yoga: ba09b6b11e6139e3df8229238aa794205ca6a02a diff --git a/src/FlashList.tsx b/src/FlashList.tsx index a4229be8..011ad255 100644 --- a/src/FlashList.tsx +++ b/src/FlashList.tsx @@ -17,19 +17,6 @@ import { useUpdateScrollViewContentSize, } from './hooks' -// Load FlashList dynamically or print a friendly error message -let AnimatedFlashList: React.ComponentClass> -try { - const flashListModule = require('@shopify/flash-list') - AnimatedFlashList = (Animated.createAnimatedComponent( - flashListModule.FlashList - ) as unknown) as React.ComponentClass> -} catch (error) { - console.error( - 'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.' - ) -} - /** * Used as a memo to prevent rerendering too often when the context changes. * See: https://github.com/facebook/react/issues/15156#issuecomment-474590693 From 1e834277711952510ba39d1498929bff88ea7510 Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Fri, 21 Apr 2023 16:34:29 -0300 Subject: [PATCH 7/8] fix: recreation of list upon props change --- example/src/Shared/ContactsFlashList.tsx | 10 +++++++-- src/FlashList.tsx | 28 +++++++++++++----------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/example/src/Shared/ContactsFlashList.tsx b/example/src/Shared/ContactsFlashList.tsx index 9379738f..7cf1e414 100644 --- a/example/src/Shared/ContactsFlashList.tsx +++ b/example/src/Shared/ContactsFlashList.tsx @@ -130,11 +130,17 @@ const Contacts: React.FC<{ nestedScrollEnabled?: boolean }> = ({ emptyContacts, nestedScrollEnabled }) => { const [isRefreshing, startRefreshing] = useRefresh() + const [data, setData] = React.useState(CONTACTS) + + React.useEffect(() => { + setInterval(() => { + setData([...CONTACTS]) + }, 10 * 1000) + }, []) return ( String(i)} + data={data} renderItem={renderItem} ItemSeparatorComponent={ItemSeparator} ListEmptyComponent={ListEmptyComponent} diff --git a/src/FlashList.tsx b/src/FlashList.tsx index 011ad255..1fdb750e 100644 --- a/src/FlashList.tsx +++ b/src/FlashList.tsx @@ -2,7 +2,7 @@ import type { FlashListProps, FlashList as SPFlashList, } from '@shopify/flash-list' -import React from 'react' +import React, { useMemo } from 'react' import Animated from 'react-native-reanimated' import { @@ -28,18 +28,20 @@ type FlashListMemoRef = SPFlashList const FlashListMemo = React.memo( React.forwardRef((props, passRef) => { // Load FlashList dynamically or print a friendly error message - try { - const flashListModule = require('@shopify/flash-list') - const AnimatedFlashList = (Animated.createAnimatedComponent( - flashListModule.FlashList - ) as unknown) as React.ComponentClass> - return - } catch (error) { - console.error( - 'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.' - ) - return <> - } + const AnimatedFlashList = useMemo(() => { + try { + const flashListModule = require('@shopify/flash-list') + return Animated.createAnimatedComponent( + flashListModule.FlashList + ) as unknown + } catch (error) { + console.error( + 'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.' + ) + } + }, []) as React.ComponentClass> + + return }) ) From eedf5c2593b7ebea4d07efaecc7f7f3f3dce13bd Mon Sep 17 00:00:00 2001 From: "Luciano J. Bracco" Date: Fri, 21 Apr 2023 17:07:08 -0300 Subject: [PATCH 8/8] fix: stable and definitive solution to list rerender --- src/FlashList.tsx | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/FlashList.tsx b/src/FlashList.tsx index 1fdb750e..bd39818e 100644 --- a/src/FlashList.tsx +++ b/src/FlashList.tsx @@ -2,7 +2,7 @@ import type { FlashListProps, FlashList as SPFlashList, } from '@shopify/flash-list' -import React, { useMemo } from 'react' +import React from 'react' import Animated from 'react-native-reanimated' import { @@ -17,6 +17,18 @@ import { useUpdateScrollViewContentSize, } from './hooks' +let AnimatedFlashList: React.ComponentClass> +try { + const flashListModule = require('@shopify/flash-list') + AnimatedFlashList = (Animated.createAnimatedComponent( + flashListModule.FlashList + ) as unknown) as React.ComponentClass> +} catch (error) { + AnimatedFlashList = (Animated.View as unknown) as React.ComponentClass< + FlashListProps + > +} + /** * Used as a memo to prevent rerendering too often when the context changes. * See: https://github.com/facebook/react/issues/15156#issuecomment-474590693 @@ -27,20 +39,6 @@ type FlashListMemoRef = SPFlashList const FlashListMemo = React.memo( React.forwardRef((props, passRef) => { - // Load FlashList dynamically or print a friendly error message - const AnimatedFlashList = useMemo(() => { - try { - const flashListModule = require('@shopify/flash-list') - return Animated.createAnimatedComponent( - flashListModule.FlashList - ) as unknown - } catch (error) { - console.error( - 'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.' - ) - } - }, []) as React.ComponentClass> - return }) ) @@ -72,6 +70,16 @@ function FlashListImpl( setRef(name, ref) }, [name, ref, setRef]) + React.useEffect(() => { + try { + require('@shopify/flash-list').FlashList + } catch (error) { + console.error( + 'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.' + ) + } + }, []) + const scrollContentSizeChange = useUpdateScrollViewContentSize({ name, })