# Performance Optimization ## Hermes Setup ### Enable Hermes **Android (android/app/build.gradle):** ```gradle project.ext.react = [ enableHermes: true ] ``` **iOS (Podfile):** ```ruby use_react_native!( :path => config[:reactNativePath], :hermes_enabled => true ) ``` ### Hermes Benefits - Faster app startup time - Reduced memory usage - Smaller bundle size - Better performance on lower-end devices ## List Optimization ### Optimized FlatList ```typescript // src/components/OptimizedList/OptimizedList.tsx import React, {useCallback, useMemo} from 'react'; import {FlatList, ListRenderItem, ViewToken} from 'react-native'; interface OptimizedListProps { data: T[]; renderItem: ListRenderItem; keyExtractor: (item: T, index: number) => string; itemHeight?: number; onEndReached?: () => void; onViewableItemsChanged?: (info: {viewableItems: ViewToken[]}) => void; } export const OptimizedList = ({ data, renderItem, keyExtractor, itemHeight = 100, onEndReached, onViewableItemsChanged, }: OptimizedListProps) => { const memoizedRenderItem = useCallback(renderItem, []); const memoizedKeyExtractor = useCallback(keyExtractor, []); const getItemLayout = useMemo( () => itemHeight ? (data: any, index: number) => ({ length: itemHeight, offset: itemHeight * index, index, }) : undefined, [itemHeight] ); const viewabilityConfig = useMemo( () => ({ itemVisiblePercentThreshold: 50, minimumViewTime: 300, }), [] ); return ( ); }; ``` ### Virtualized List for Large Datasets ```typescript // src/components/VirtualizedList/VirtualizedList.tsx import React from 'react'; import {VirtualizedList, ListRenderItem} from 'react-native'; interface VirtualizedListProps { data: T[]; renderItem: ListRenderItem; keyExtractor: (item: T, index: number) => string; itemHeight: number; } export const CustomVirtualizedList = ({ data, renderItem, keyExtractor, itemHeight, }: VirtualizedListProps) => { const getItem = (data: T[], index: number) => data[index]; const getItemCount = (data: T[]) => data.length; return ( ({ length: itemHeight, offset: itemHeight * index, index, })} /> ); }; ``` ## Image Optimization ### Lazy Loading Images ```typescript // src/components/LazyImage/LazyImage.tsx import React, {useState, useRef} from 'react'; import {View, Image, Animated, StyleSheet} from 'react-native'; import FastImage from 'react-native-fast-image'; interface LazyImageProps { source: {uri: string}; style?: any; placeholder?: React.ReactNode; } export const LazyImage: React.FC = ({ source, style, placeholder, }) => { const [loaded, setLoaded] = useState(false); const opacity = useRef(new Animated.Value(0)).current; const onLoad = () => { setLoaded(true); Animated.timing(opacity, { toValue: 1, duration: 300, useNativeDriver: true, }).start(); }; return ( {!loaded && placeholder} ); }; ``` ## Memory Management ### Component Memoization ```typescript // src/components/MemoizedComponent/MemoizedComponent.tsx import React, {memo, useMemo, useCallback} from 'react'; import {View, Text, TouchableOpacity} from 'react-native'; interface ItemProps { id: string; title: string; description: string; onPress: (id: string) => void; } const ItemComponent: React.FC = memo(({ id, title, description, onPress, }) => { const handlePress = useCallback(() => { onPress(id); }, [id, onPress]); const formattedDescription = useMemo(() => { return description.length > 100 ? `${description.substring(0, 100)}...` : description; }, [description]); return ( {title} {formattedDescription} ); }); export default ItemComponent; ``` ### Custom Hooks Optimization ```typescript // src/hooks/useOptimizedData.ts import {useMemo, useCallback} from 'react'; import {useAppSelector} from '@redux/hooks'; export const useOptimizedData = (filter?: string) => { const rawData = useAppSelector(state => state.data.items); const filteredData = useMemo(() => { if (!filter) return rawData; return rawData.filter(item => item.title.toLowerCase().includes(filter.toLowerCase()) ); }, [rawData, filter]); const processItem = useCallback((item: any) => { return { ...item, displayTitle: item.title.toUpperCase(), isNew: Date.now() - item.createdAt < 86400000, // 24 hours }; }, []); const processedData = useMemo(() => filteredData.map(processItem), [filteredData, processItem] ); return processedData; }; ``` ## Bundle Optimization ### Code Splitting ```typescript // src/utils/lazyImports.ts import {lazy} from 'react'; // Lazy load heavy screens export const ProfileScreen = lazy(() => import('@screens/Profile/ProfileScreen')); export const SettingsScreen = lazy(() => import('@screens/Settings/SettingsScreen')); export const ReportsScreen = lazy(() => import('@screens/Reports/ReportsScreen')); // Lazy load heavy components export const ChartComponent = lazy(() => import('@components/Chart/ChartComponent')); export const MapComponent = lazy(() => import('@components/Map/MapComponent')); ``` ### Dynamic Imports ```typescript // src/utils/dynamicImports.ts export const loadChartLibrary = async () => { const {Chart} = await import('react-native-chart-kit'); return Chart; }; export const loadMapLibrary = async () => { const MapView = await import('react-native-maps'); return MapView.default; }; // Usage in component const MyComponent = () => { const [ChartComponent, setChartComponent] = useState(null); useEffect(() => { loadChartLibrary().then(setChartComponent); }, []); return ChartComponent ? : ; }; ``` ## Animation Optimization ### Native Driver Usage ```typescript // src/animations/optimizedAnimations.ts import {Animated, Easing} from 'react-native'; export const createOptimizedAnimation = ( animatedValue: Animated.Value, toValue: number, duration: number = 300 ) => { return Animated.timing(animatedValue, { toValue, duration, easing: Easing.out(Easing.quad), useNativeDriver: true, // Use native driver for better performance }); }; export const createSpringAnimation = ( animatedValue: Animated.Value, toValue: number ) => { return Animated.spring(animatedValue, { toValue, tension: 100, friction: 8, useNativeDriver: true, }); }; ``` ## Network Optimization ### Request Batching ```typescript // src/utils/requestBatcher.ts class RequestBatcher { private queue: Array<{ url: string; options: RequestInit; resolve: (value: any) => void; reject: (reason: any) => void; }> = []; private batchTimeout: NodeJS.Timeout | null = null; public request(url: string, options: RequestInit = {}): Promise { return new Promise((resolve, reject) => { this.queue.push({url, options, resolve, reject}); if (this.batchTimeout) { clearTimeout(this.batchTimeout); } this.batchTimeout = setTimeout(() => { this.processBatch(); }, 50); // Batch requests within 50ms }); } private async processBatch() { const batch = [...this.queue]; this.queue = []; this.batchTimeout = null; // Group similar requests const grouped = batch.reduce((acc, req) => { const key = `${req.options.method || 'GET'}-${req.url.split('?')[0]}`; if (!acc[key]) acc[key] = []; acc[key].push(req); return acc; }, {} as Record); // Process each group for (const requests of Object.values(grouped)) { try { const results = await Promise.all( requests.map(req => fetch(req.url, req.options)) ); results.forEach((result, index) => { requests[index].resolve(result); }); } catch (error) { requests.forEach(req => req.reject(error)); } } } } export const requestBatcher = new RequestBatcher(); ``` ## Performance Monitoring ### Performance Metrics ```typescript // src/utils/performanceMonitor.ts class PerformanceMonitor { private metrics: Map = new Map(); startTiming(label: string) { this.metrics.set(label, Date.now()); } endTiming(label: string): number { const startTime = this.metrics.get(label); if (!startTime) { console.warn(`No start time found for ${label}`); return 0; } const duration = Date.now() - startTime; this.metrics.delete(label); console.log(`${label}: ${duration}ms`); return duration; } measureAsync(label: string, fn: () => Promise): Promise { this.startTiming(label); return fn().finally(() => { this.endTiming(label); }); } measureSync(label: string, fn: () => T): T { this.startTiming(label); try { return fn(); } finally { this.endTiming(label); } } } export const performanceMonitor = new PerformanceMonitor(); // Usage performanceMonitor.measureAsync('API_CALL', () => fetch('/api/data').then(res => res.json()) ); ``` ### Memory Usage Tracking ```typescript // src/utils/memoryTracker.ts export const trackMemoryUsage = () => { if (__DEV__) { const memoryInfo = (performance as any).memory; if (memoryInfo) { console.log('Memory Usage:', { used: Math.round(memoryInfo.usedJSHeapSize / 1048576) + ' MB', total: Math.round(memoryInfo.totalJSHeapSize / 1048576) + ' MB', limit: Math.round(memoryInfo.jsHeapSizeLimit / 1048576) + ' MB', }); } } }; // Track memory usage periodically setInterval(trackMemoryUsage, 30000); // Every 30 seconds in development ```