Performance is critical for mobile applications. Users expect smooth, responsive experiences, and poor performance can lead to app abandonment. This article covers proven techniques for optimizing React Native applications.
List Rendering Optimization
Lists are common in mobile apps and can be performance bottlenecks:
typescript
// ✅ Optimized FlatList
import { FlatList } from 'react-native';
function OptimizedList({ data }: { data: Item[] }) {
const renderItem = useCallback(({ item }: { item: Item }) => {
return <ListItem item={item} />;
}, []);
const keyExtractor = useCallback((item: Item) => item.id, []);
const getItemLayout = useCallback(
(_: any, index: number) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
}),
[]
);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
getItemLayout={getItemLayout}
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={10}
removeClippedSubviews={true}
/>
);
}
// ❌ Bad: Using ScrollView for lists
function BadList({ data }: { data: Item[] }) {
return (
<ScrollView>
{data.map(item => <ListItem key={item.id} item={item} />)}
</ScrollView>
);
}Image Optimization
Images are often the largest assets in mobile apps:
typescript
// ✅ Using react-native-fast-image
import FastImage from 'react-native-fast-image';
function OptimizedImage({ uri }: { uri: string }) {
return (
<FastImage
source={{
uri,
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable,
}}
resizeMode={FastImage.resizeMode.cover}
style={{ width: 200, height: 200 }}
/>
);
}
// ✅ Image caching strategy
const imageCache = {
get: (uri: string) => {
// Check memory cache
// Check disk cache
// Return cached image or null
},
set: (uri: string, image: Image) => {
// Store in memory cache
// Store in disk cache
},
};Component Optimization
typescript
// ✅ Memoizing expensive components
const ExpensiveListItem = React.memo(({ item }: { item: Item }) => {
return (
<View>
<Text>{item.title}</Text>
<ComplexVisualization data={item.data} />
</View>
);
}, (prevProps, nextProps) => {
// Custom comparison
return prevProps.item.id === nextProps.item.id;
});
// ✅ Using useMemo for expensive calculations
function ProductList({ products }: { products: Product[] }) {
const sortedProducts = useMemo(() => {
return products.sort((a, b) => a.price - b.price);
}, [products]);
return (
<FlatList
data={sortedProducts}
renderItem={({ item }) => <ProductCard product={item} />}
/>
);
}Animation Performance
Smooth animations are crucial for user experience:
typescript
// ✅ Using Reanimated for smooth animations
import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
function AnimatedButton() {
const scale = useSharedValue(1);
const handlePress = () => {
scale.value = withSpring(0.95, {
damping: 15,
stiffness: 150,
});
setTimeout(() => {
scale.value = withSpring(1);
}, 100);
};
return (
<Animated.View style={{ transform: [{ scale }] }}>
<Button onPress={handlePress} />
</Animated.View>
);
}
// ✅ Using native driver
const animatedValue = new Animated.Value(0);
Animated.timing(animatedValue, {
toValue: 1,
duration: 300,
useNativeDriver: true, // ✅ Use native driver
}).start();Memory Management
Proper memory management prevents crashes:
typescript
// ✅ Cleaning up subscriptions
function UserProfile({ userId }: { userId: string }) {
useEffect(() => {
const subscription = userService.subscribe(userId, (user) => {
setUser(user);
});
// Cleanup
return () => {
subscription.unsubscribe();
};
}, [userId]);
return <UserDetails user={user} />;
}
// ✅ Limiting image cache
import { ImageCache } from 'react-native-fast-image';
ImageCache.get().clear(); // Clear cache when needed
ImageCache.get().limit(50); // Limit cache sizeConclusion
React Native performance optimization is an ongoing process. By following these techniques and regularly profiling your application, you can create smooth, responsive mobile experiences that users love. Remember to measure before and after optimizations to ensure they're effective.