Performance Optimization di React Native
Mobile device punya resource terbatas — CPU, RAM, battery. Optimasi performa bukan nice-to-have, tapi keharusan untuk user experience yang baik.
Hermes Engine
// Hermes: JS engine optimized untuk React Native
// Default di Expo SDK 50+ dan React Native 0.70+
// Keuntungan Hermes:
// - Startup time 2x lebih cepat
// - Memory usage 30% lebih rendah
// - Bytecode precompilation (AOT)
// Cek apakah Hermes aktif:
const isHermes = () => !!global.HermesInternal;
console.log('Hermes:', isHermes()); // true
FlatList Optimization
import { FlatList } from 'react-native';
import { memo, useCallback } from 'react';
// 1. Memoize render item
const MemoizedItem = memo(({ item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
));
function OptimizedList({ data }) {
// 2. Stable callbacks
const renderItem = useCallback(
({ item }) => <MemoizedItem item={item} />,
[]
);
const keyExtractor = useCallback((item) => item.id.toString(), []);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
// 3. Tuning props
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={5}
removeClippedSubviews={true}
// 4. Estimated item size (skip layout calculation)
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
);
}
FlashList — FlatList Replacement
import { FlashList } from '@shopify/flash-list';
// Drop-in replacement, 5x lebih cepat dari FlatList
<FlashList
data={data}
renderItem={({ item }) => <ItemComponent item={item} />}
estimatedItemSize={80}
/>
Image Optimization
// expo-image: pengganti Image bawaan, jauh lebih cepat
import { Image } from 'expo-image';
<Image
source={{ uri: imageUrl }}
style={{ width: 200, height: 200 }}
contentFit="cover"
placeholder={blurhash} // Placeholder blur saat loading
transition={200} // Fade-in animation
cachePolicy="memory-disk" // Aggressive caching
/>
Avoid Re-renders
// BURUK: inline object/function = re-render setiap render cycle
<View style={{ padding: 16 }}> {/* Buat object baru setiap render */}
<Pressable onPress={() => doSomething()}> {/* Function baru */}
<Text>Press</Text>
</Pressable>
</View>
// BAIK: stable reference
const styles = StyleSheet.create({ container: { padding: 16 } });
const handlePress = useCallback(() => doSomething(), []);
<View style={styles.container}>
<Pressable onPress={handlePress}>
<Text>Press</Text>
</Pressable>
</View>
Profiling Tools
- React DevTools Profiler — Detect unnecessary re-renders
- Flipper — Network inspector, layout inspector, performance monitor
- Xcode Instruments — CPU, memory, energy profiling (iOS)
- Android Studio Profiler — CPU, memory, network (Android)
- React Native Perf Monitor —
ctrl+M/ shake → Show Perf Monitor