Introduction
A slow app frustrates users. React Native powers Instagram, Facebook, and others - but requires optimization. This guide covers making your React Native app fast and smooth.
Performance Pillars
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ React Native Performance โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ 1. JS Thread โ
โ โข Runs your JavaScript โ
โ โข UI updates, business logic โ
โ โข Blocked = janky UI โ
โ โ
โ 2. UI Thread (Main) โ
โ โข Native rendering โ
โ โข Layout calculations โ
โ โข Animations โ
โ โ
โ 3. Memory โ
โ โข Excessive re-renders โ
โ โข Large data in memory โ
โ โข Memory leaks โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Enable Hermes
// app.json
{
"expo": {
"jsEngine": "hermes"
}
}
// Check Hermes is enabled
import { HermesEngine } from 'react-native';
console.log(HermesEngine.isEnabled()); // true
List Optimization
FlatList Best Practices
// โ Bad - No optimization
<FlatList
data={items}
renderItem={({ item }) => <ItemComponent item={item} />}
/>
// โ
Good - Optimized
<FlatList
data={items}
renderItem={({ item }) => <ItemComponent item={item} />}
keyExtractor={item => item.id}
getItemLayout={(_, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={10}
initialNumToRender={10}
ListHeaderComponent={Header}
ListFooterComponent={Footer}
/>
Virtualization
// Use FlashList for even better performance
import { FlashList } from '@shopify/flash-list';
<FlashList
data={items}
renderItem={({ item }) => <ItemComponent item={item} />}
estimatedItemSize={100}
/>
Memoization
// Prevent unnecessary re-renders
import { memo, useCallback, useMemo } from 'react';
// Memoize components
const Item = memo(({ title, onPress }) => (
<TouchableOpacity onPress={onPress}>
<Text>{title}</Text>
</TouchableOpacity>
));
// Memoize callbacks
const handlePress = useCallback((id: string) => {
navigation.navigate('Detail', { id });
}, [navigation]);
// Memoize expensive computations
const processedData = useMemo(() => {
return data.map(item => transform(item));
}, [data]);
Image Optimization
import { Image } from 'react-native';
import { FastImage } from 'react-native-fast-image';
// Use FastImage for caching
<FastImage
source={{ uri: 'https://example.com/image.jpg' }}
style={{ width: 100, height: 100 }}
resizeMode={FastImage.resizeMode.cover}
/>
// Or use expo-image
import { Image } from 'expo-image';
<Image
source="https://example.com/image.jpg"
style={{ width: 100, height: 100 }}
contentFit="cover"
cachePolicy="memory-disk"
/>
Performance Monitoring
import { PerformanceMonitor } from 'expo-performance';
// Measure execution time
const { start, end } = await PerformanceMonitor.startMeasure('my-task');
await doExpensiveTask();
end();
// Check frame rate
import { useFrameRate } from 'expo-performance';
function MyComponent() {
const frameRate = useFrameRate();
return <Text>FPS: {frameRate}</Text>;
}
Key Takeaways
- Hermes - Enable for better performance
- FlatList - Configure virtualization
- Memoization - Prevent re-renders
- Images - Use cached images
- Monitor - Measure performance
Comments