Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: FlashList re-render issue #333

Closed
12 changes: 6 additions & 6 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -526,7 +526,7 @@ SPEC CHECKSUMS:
FBLazyVector: a83ceaa8a8581003a623facdb3c44f6d4f342ac5
FBReactNativeSpec: 85eee79837cb797ab6176f0243a2b40511c09158
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
glog: 476ee3e89abb49e07f822b48323c51c57124b572
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
RCTRequired: 5c6fd63b03abb06947d348dadac51c93e3485bd8
RCTTypeSafety: 1c66daedd66f674e39ce9f40782f0d490c78b175
Expand Down Expand Up @@ -562,4 +562,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 4a1d4df08804ad081db13b6bea02bebbb098497a

COCOAPODS: 1.12.1
COCOAPODS: 1.11.3
10 changes: 8 additions & 2 deletions example/src/Shared/ContactsFlashList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Tabs.FlashList
data={emptyContacts ? [] : CONTACTS}
keyExtractor={(_, i) => String(i)}
data={data}
renderItem={renderItem}
ItemSeparatorComponent={ItemSeparator}
ListEmptyComponent={ListEmptyComponent}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
36 changes: 23 additions & 13 deletions src/FlashList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ import {
useUpdateScrollViewContentSize,
} from './hooks'

let AnimatedFlashList: React.ComponentClass<FlashListProps<any>>
try {
const flashListModule = require('@shopify/flash-list')
AnimatedFlashList = (Animated.createAnimatedComponent(
flashListModule.FlashList
) as unknown) as React.ComponentClass<FlashListProps<any>>
} catch (error) {
AnimatedFlashList = (Animated.View as unknown) as React.ComponentClass<
FlashListProps<any>
>
}

/**
* Used as a memo to prevent rerendering too often when the context changes.
* See: https://github.com/facebook/react/issues/15156#issuecomment-474590693
Expand All @@ -27,19 +39,7 @@ type FlashListMemoRef = SPFlashList<any>

const FlashListMemo = React.memo(
React.forwardRef<FlashListMemoRef, FlashListMemoProps>((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<FlashListProps<any>>
return <AnimatedFlashList ref={passRef} {...props} />
} catch (error) {
console.error(
'The optional dependency @shopify/flash-list is not installed. Please install it to use the FlashList component.'
)
return <></>
}
return <AnimatedFlashList ref={passRef} {...props} />
})
)

Expand Down Expand Up @@ -70,6 +70,16 @@ function FlashListImpl<R>(
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,
})
Expand Down