Description
I'm seeing a significant slowdown in rendering when I add a Swipeable to the items in a FlatList.
This visually looks about 2x slower on my Androids (emulator, old device, newer device). iOS is less noticeable (iPhone 11) but from what I've profiled it looks like iOS is also slowing down.
By eye it looks like my screen takes ~2s to render on my newer device (~3s on the older device/emulator) with Swipeable present but ~0.5s (~1s on the older device/emulator) when I delete the Swipeable.
I've tried to create a Snack, but it seems to be using Expo 51 and I'm seeing this in Expo 52 with New Architecture. I've still given the link to the Snack below just in case this is helpful.
Steps to reproduce
I wanted to provide as useful an issue as I can in the hope this is helpful, so I've done my best to optimise and strip down my code (see below) and then profiled performance when the Swipeable component is present and, for comparison, when I delete it.
- Add swipeable to a list item in FlatList (I think other similar lists too)
- Render performance is significantly slower
- Remove Swipeable (everything else unchanged) and performance increases noticeably
I've optimised what I can in my code (memo and useCallback) and stripped it back in case it's something else I'm doing. I'm including the code below.
I then used the profiler to see where the slowdown is coming from. Swipeable seems to be taking a chunk of time on each item. I'm including screenshots and exported profile data. I've highlighted the VirtualizedList component with a red dot in the screenshots for visual comparison. The trace highlihts Swipeable in yellow for items rendered.
Performance profiles:
With Swipeable

swipeable-profiling-data.17-01-2025.22-03-28.json
Without Swipeable

no-swipeable-profiling-data.17-01-2025.22-08-42.json
Code
Stripped back as much as possible to make it easier to reproduce if needed.
The Swipeable is the outermost component of the SearchResult list item. Deleting the Swipeable significantly reduces rendering time, particularly noticeable on Android, especially an older real device I'm testing with:
import { memo, ReactElement, useCallback } from 'react';
import { StyleSheet, View, FlatList, Pressable, Text } from 'react-native';
import { Image } from 'expo-image';
import Swipeable from 'react-native-gesture-handler/ReanimatedSwipeable';
const deleteIcon = require('../assets/icons/trash.svg');
export interface Client {
id: string,
firstName: string,
lastName?: string,
}
interface SearchResultProps {
client: Client,
onSelect: (client: Client) => void,
renderRightActions: (client: Client) => ReactElement,
}
interface ClientListProps {
clients: Client[];
onDelete: (id: string) => void,
}
/**
* List item
*/
export const SearchResult = memo(({
client,
onSelect,
renderRightActions,
}: SearchResultProps) => {
return (
// This Swipeable seems to cause the issue
<Swipeable renderRightActions={() => renderRightActions(client)} containerStyle={{ borderRadius: 999, backgroundColor: 'gray', height: 48, marginBottom: 12 }}>
<View style={styles.searchResult}>
<Pressable onPress={() => onSelect(client)}>
<View style={styles.searchResultRow}>
<Text style={styles.searchResultText}>{client.firstName} {client.lastName}</Text>
</View>
</Pressable>
</View>
</Swipeable>
);
}, (prevProps, nextProps) => {
return (
prevProps.client.firstName === nextProps.client.firstName &&
prevProps.client.lastName === nextProps.client.lastName
);
});
/**
* FlatList
*/
export default function ClientList({ clients, onDelete }: ClientListProps): ReactElement {
// Create a render function for the left swipe action (delete)
const renderRightActions = useCallback((client: Client) => (
<Pressable onPress={() => { onDelete(client.id); }} style={styles.actionButton}>
<View style={styles.actionIconContainer}>
<Image source={deleteIcon} style={[styles.actionIcon, { tintColor: 'white' }]} contentFit="contain" testID="deleteIcon" />
</View>
</Pressable>
), []);
const renderitem = useCallback(({ item }: { item: Client, index: number; }) => (
<SearchResult client={item} onSelect={() => { }} renderRightActions={renderRightActions} />
), []);
return (
<View style={{ flex: 1 }}>
<View style={styles.searchResultsContainer}>
<FlatList
data={clients}
keyExtractor={(i) => i.id}
renderItem={renderitem}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
searchResultsContainer: {
flex: 4,
backgroundColor: 'white',
},
actionButton: {
width: 48,
height: 48,
borderRadius: 999,
backgroundColor: 'red',
},
actionIconContainer: {
height: '100%',
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
actionIcon: {
height: 28,
width: 28,
},
searchResult: {
marginBottom: 12, // Make up for 'gap' not working in FlatList
},
searchResultRow: {
height: 48,
flexDirection: 'row',
gap: 16,
alignItems: 'center',
backgroundColor: 'white',
borderRadius: 999,
},
searchResultText: {
fontSize: 16,
lineHeight: 24,
color: 'black',
},
});
"react-native-gesture-handler": "~2.20.2",
"react-native-reanimated": "~3.16.1"
Snack or a link to a repository
https://snack.expo.dev/@davidcarboni/swipeable-performance
Gesture Handler version
~2.20.2
React Native version
0.76.6
Platforms
Android, iOS
JavaScript runtime
Hermes
Workflow
Expo managed workflow
Architecture
Fabric (New Architecture)
Build type
Debug mode
Device
Real device
Device model
OnePlus 9, OnePlus 5 (also Android Emulator and iPhone 11)
Acknowledgements
Yes
Description
I'm seeing a significant slowdown in rendering when I add a
Swipeableto the items in a FlatList.This visually looks about 2x slower on my Androids (emulator, old device, newer device). iOS is less noticeable (iPhone 11) but from what I've profiled it looks like iOS is also slowing down.
By eye it looks like my screen takes ~2s to render on my newer device (~3s on the older device/emulator) with
Swipeablepresent but ~0.5s (~1s on the older device/emulator) when I delete theSwipeable.I've tried to create a Snack, but it seems to be using Expo 51 and I'm seeing this in Expo 52 with New Architecture. I've still given the link to the Snack below just in case this is helpful.
Steps to reproduce
I wanted to provide as useful an issue as I can in the hope this is helpful, so I've done my best to optimise and strip down my code (see below) and then profiled performance when the
Swipeablecomponent is present and, for comparison, when I delete it.I've optimised what I can in my code (
memoanduseCallback) and stripped it back in case it's something else I'm doing. I'm including the code below.I then used the profiler to see where the slowdown is coming from.
Swipeableseems to be taking a chunk of time on each item. I'm including screenshots and exported profile data. I've highlighted theVirtualizedListcomponent with a red dot in the screenshots for visual comparison. The trace highlihtsSwipeablein yellow for items rendered.Performance profiles:
With Swipeable
swipeable-profiling-data.17-01-2025.22-03-28.json
Without Swipeable
no-swipeable-profiling-data.17-01-2025.22-08-42.json
Code
Stripped back as much as possible to make it easier to reproduce if needed.
The
Swipeableis the outermost component of theSearchResultlist item. Deleting theSwipeablesignificantly reduces rendering time, particularly noticeable on Android, especially an older real device I'm testing with:Snack or a link to a repository
https://snack.expo.dev/@davidcarboni/swipeable-performance
Gesture Handler version
~2.20.2
React Native version
0.76.6
Platforms
Android, iOS
JavaScript runtime
Hermes
Workflow
Expo managed workflow
Architecture
Fabric (New Architecture)
Build type
Debug mode
Device
Real device
Device model
OnePlus 9, OnePlus 5 (also Android Emulator and iPhone 11)
Acknowledgements
Yes