C

Complete React Native Optimization Studio

Streamline your workflow with this skill for performance optimization for mobile React apps. Built for Claude Code with best practices and real-world patterns.

SkillCommunityfrontendv1.0.0MIT
0 views0 copies

React Native Optimization Studio

Performance optimization toolkit for React Native applications covering rendering performance, memory management, bundle optimization, startup time reduction, and platform-specific tuning.

When to Use This Skill

Choose React Native Optimization when:

  • App has janky animations or slow scrolling (FPS drops below 60)
  • Startup time exceeds 2 seconds on target devices
  • Memory usage causes crashes on lower-end devices
  • Bundle size is too large for app store requirements
  • Need to optimize list rendering for large datasets

Consider alternatives when:

  • Building a new app from scratch — start with good architecture first
  • Need native-only optimization — use Xcode Instruments or Android Profiler
  • Performance issues are server-side — optimize API endpoints

Quick Start

# Activate React Native optimization claude skill activate complete-react-native-optimization-studio # Profile performance claude "Analyze the React Native app for performance bottlenecks" # Optimize a specific screen claude "Optimize the FlatList performance on the feed screen"

Example: Optimized FlatList

import { FlashList } from '@shopify/flash-list'; import { useCallback, useMemo } from 'react'; interface FeedScreenProps { posts: Post[]; } export function FeedScreen({ posts }: FeedScreenProps) { const renderItem = useCallback(({ item }: { item: Post }) => ( <PostCard post={item} /> ), []); const keyExtractor = useCallback((item: Post) => item.id, []); const getItemType = useCallback((item: Post) => { return item.hasImage ? 'image-post' : 'text-post'; }, []); return ( <FlashList data={posts} renderItem={renderItem} keyExtractor={keyExtractor} estimatedItemSize={200} getItemType={getItemType} // Performance optimizations removeClippedSubviews={true} maxToRenderPerBatch={10} windowSize={5} initialNumToRender={10} /> ); } // Memoized card component const PostCard = React.memo(function PostCard({ post }: { post: Post }) { return ( <View style={styles.card}> <Text style={styles.title}>{post.title}</Text> {post.hasImage && ( <FastImage source={{ uri: post.imageUrl, priority: FastImage.priority.normal }} style={styles.image} resizeMode={FastImage.resizeMode.cover} /> )} <Text style={styles.body}>{post.excerpt}</Text> </View> ); });

Core Concepts

Performance Metrics

MetricTargetHow to Measure
JS Frame Rate60 FPSReact Native Perf Monitor
UI Frame Rate60 FPSPlatform profilers
TTI (Time to Interactive)<2sFlipper, custom timing
Memory Usage<200MBXcode Instruments, Android Profiler
Bundle Size<15MB (JS)Metro bundle analysis
App Launch<1.5s cold startPlatform startup profiling

Common Optimization Areas

AreaProblemSolution
ListsScroll jank, high memoryFlashList, virtualization, memoization
ImagesSlow loading, memory pressureFastImage, caching, lazy loading
NavigationSlow screen transitionsLazy loading screens, native-stack
AnimationsDropped framesReanimated 3, native driver
BridgeSerialization overheadNew Architecture (JSI/Turbo Modules)
StartupSlow cold startHermes, inline requires, preloading
// Animation optimization with Reanimated import Animated, { useSharedValue, useAnimatedStyle, withSpring, runOnUI, } from 'react-native-reanimated'; function AnimatedCard({ onPress }: { onPress: () => void }) { const scale = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], })); const handlePressIn = () => { scale.value = withSpring(0.95, { damping: 15, stiffness: 150 }); }; const handlePressOut = () => { scale.value = withSpring(1, { damping: 15, stiffness: 150 }); }; return ( <Pressable onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={onPress}> <Animated.View style={[styles.card, animatedStyle]}> {/* Card content */} </Animated.View> </Pressable> ); }

Configuration

ParameterDescriptionDefault
hermes_enabledUse Hermes JavaScript enginetrue
new_architectureEnable Fabric + TurboModulesfalse
flipper_enabledEnable Flipper debugging (dev only)true
inline_requiresEnable inline requires for faster startuptrue
ram_bundleUse RAM bundle formatfalse
proguardEnable ProGuard for Androidtrue

Best Practices

  1. Use FlashList instead of FlatList for all lists — Shopify's FlashList is a drop-in replacement that recycles cell components instead of creating new ones, achieving consistent 60 FPS even with complex list items and thousands of entries.

  2. Move all animations to the UI thread with Reanimated — React Native's Animated API with useNativeDriver: true is limited. Reanimated 3 runs animation worklets on the UI thread, enabling complex gesture-driven animations at 60 FPS without bridge overhead.

  3. Enable Hermes and inline requires for faster startup — Hermes precompiles JavaScript to bytecode, reducing parse time by 50-80%. Inline requires defer module loading until first use, reducing startup bundle evaluation.

  4. Use React.memo with custom comparators for list items — Wrap list item components in React.memo and provide a comparison function that checks only the props that affect rendering. This prevents unnecessary re-renders when parent state changes.

  5. Profile on real devices, not simulators — Simulators run on desktop hardware and don't reflect real device performance. Always test performance on the lowest-spec device in your target audience. Use release builds for accurate profiling — debug mode adds significant overhead.

Common Issues

FlatList drops frames when scrolling through image-heavy content. Replace FlatList with FlashList and use react-native-fast-image instead of the built-in Image component. FastImage handles caching, prioritization, and progressive loading. Set removeClippedSubviews={true} and reduce windowSize to limit off-screen rendering.

App crashes with "out of memory" on older Android devices. Large images are the most common cause. Resize images server-side to match display dimensions, use progressive JPEG loading, and implement image cache size limits. Monitor memory with Android Profiler and set largeHeap: true in AndroidManifest only as a last resort.

Navigation transitions are slow and choppy. Use @react-navigation/native-stack instead of @react-navigation/stack for native transition animations. Lazy-load screen components with React.lazy() and wrap with <Suspense>. Avoid heavy computations during the transition by deferring data loading with InteractionManager.runAfterInteractions().

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates