React Native Performance: Practical Optimization Tips
Battle-tested techniques to make your React Native app faster, from reducing re-renders to optimizing images and lists.
After years of building React Native apps, I've collected optimization techniques that actually matter. Skip the premature optimization - focus on these high-impact areas.
Measure First
Before optimizing, measure. React Native has built-in tools:
// Enable performance monitor
import { PerformanceMonitor } from 'react-native';
// In development, shake device and enable "Perf Monitor"
Look for:
- JS frame rate (should be 60fps)
- UI frame rate (should be 60fps)
- RAM usage
1. Fix Re-renders
The biggest performance killer. Use React DevTools Profiler to find components re-rendering unnecessarily.
Use React.memo wisely
const ExpensiveComponent = React.memo(({ data }) => {
// Only re-renders when data changes
return <ComplexView data={data} />;
});
Stabilize callbacks with useCallback
// Bad - creates new function every render
<Button onPress={() => handlePress(id)} />
// Good - stable reference const handlePressCallback = useCallback(() => { handlePress(id); }, [id]); <Button onPress={handlePressCallback} />
2. Optimize Lists
FlatList is powerful but needs tuning:
<FlatList
data={items}
renderItem={renderItem}
keyExtractor={item => item.id}
// Performance props
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
initialNumToRender={10}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
For complex items, extract to a memoized component:
const ListItem = React.memo(({ item, onPress }) => (
<TouchableOpacity onPress={() => onPress(item.id)}>
<Text>{item.title}</Text>
</TouchableOpacity>
));
3. Image Optimization
Images are often the slowest part:
// Use FastImage for caching
import FastImage from 'react-native-fast-image';
<FastImage source={{ uri: imageUrl, priority: FastImage.priority.normal }} resizeMode={FastImage.resizeMode.cover} />
Also:
- Serve correctly sized images (don't download 4K for a thumbnail)
- Use WebP format when possible
- Implement progressive loading for large images
4. Reduce Bundle Size
Large bundles = slow startup:
# Analyze your bundle
npx react-native-bundle-visualizer
Common fixes:
- Replace moment.js with date-fns
- Use lodash-es and import only what you need
- Lazy load heavy screens
5. Native Driver Animations
Always use native driver when possible:
Animated.timing(fadeAnim, {
toValue: 1,
duration: 300,
useNativeDriver: true, // This is key
}).start();
Native driver limitations:
- Only works with transform and opacity
- Can't animate layout properties (width, height, margin)
import Animated, {
useSharedValue,
withSpring
} from 'react-native-reanimated';
const offset = useSharedValue(0); offset.value = withSpring(100);
Real Impact
Applying these to a client app:
- Startup time: 3.2s → 1.8s
- List scrolling: 45fps → 60fps
- Memory usage: 180MB → 120MB