React Native Code Review Checklist
Rapid-scan checklist for React Native mobile application code reviews.
React Web vs React Native
This checklist focuses on mobile-specific concerns. For common React patterns (hooks, state, performance), also reference React Code Review Checklist.
Security Red Flags - Block PR Immediately
- Sensitive data in AsyncStorage: Tokens, passwords, PINs stored unencrypted → Use Keychain/Keystore → React Native Security - Secure Storage
- API keys in source code: Credentials hardcoded in components, constants, or .env files in repo
- Missing certificate pinning: Production API calls without certificate pinning → React Native Security - Certificate Pinning
- dangerouslySetInnerHTML in WebView: HTML injection in WebView content
- Deep links without validation: Opening URLs from
Linking.openURLwithout validation - Jailbreak/root detection disabled: Production builds without security checks on compromised devices
- ProGuard/R8 disabled: Android release builds without code obfuscation
- Hermes disabled in production: Missing bytecode obfuscation for iOS
- Insecure HTTP allowed:
NSAllowsArbitraryLoadsenabled or cleartext traffic permitted - Biometric auth bypassed: Fallback authentication without server validation
Common Mistakes
React Native Specific
- Network requests on main thread (should be async) → React Native Performance
- Large images not optimized (use FastImage, webp format)
- FlatList without
keyExtractoror improperkeyvalues - Missing
removeClippedSubviewson long FlatLists - ScrollView with many children instead of FlatList/SectionList
- Animated values not using native driver when possible
- Not using Hermes JavaScript engine (better performance)
Platform-Specific Issues
- Missing
Platform.OSchecks for platform-specific code - Not using
Platform.selectfor cross-platform values - iOS-specific code without Android equivalent (or vice versa)
- Missing SafeAreaView on iOS (content hidden by notch/home indicator)
- Not handling Android back button
- Permission requests without platform-specific handling
Navigation
- Navigator mounted inside component that re-renders → React Native Navigation
- Missing deep link handling
- No loading states during navigation transitions
- Navigation state stored in global state (should use navigation state)
- Passing large objects via navigation params instead of IDs
Hooks & Effects
- See React Code Review - Hooks for common React hook issues
- Event listeners not removed on unmount (NetInfo, AppState, keyboard events)
- BackHandler listener not removed on unmount
- Not cancelling fetch requests on unmount
State Management
- Overusing global state for local UI state → React Native Data
- Not persisting critical state (user preferences, cart, draft data)
- Storing sensitive data in persisted Redux/Zustand (should use Keychain)
- Missing offline queue for failed network requests
Watch For - Performance & Mobile-Specific Issues
Performance
- Long initial load time (> 3 seconds on mid-range devices)
- Slow FlatList scrolling (not hitting 60fps) → React Native Performance - List Optimization
- Images not cached (use
react-native-fast-image) - Missing image size optimization (retina images on low-DPI screens)
- Animations janky (< 60fps, not using native driver)
- Large bundle size (> 20MB for Android, > 50MB for iOS)
- Missing bundle splitting or lazy loading for large apps
- Memory leaks from retained references or listeners
FlatList Issues
- Missing
getItemLayoutfor fixed-height items (improves scroll performance) - No
windowSizeoptimization (defaults may be too large) - Missing
removeClippedSubviews={true}for very long lists - Re-rendering entire list when data changes (missing proper
keyExtractor) - Inline functions in
renderItemwithoutuseCallback
Memory & Leaks
- High-resolution images loaded for list items
- Images not released from memory when off-screen
- Subscriptions to native modules not cleaned up
- Event emitters not removed on unmount
- Timers not cleared when component unmounts
- Large objects held in state unnecessarily
Network
- No request timeout configured → React Native Data - API Integration
- Missing retry logic for failed requests
- Not handling offline scenarios gracefully
- Fetching large payloads without pagination
- Missing request/response interceptors for auth tokens
- No request deduplication
Offline Support
- No offline persistence for critical data → React Native Data
- Missing network state detection (NetInfo)
- No offline queue for mutations
- Not syncing local changes when back online
- Missing conflict resolution for offline edits
Platform Differences
- UI doesn't match platform conventions (Material on iOS, Cupertino on Android)
- Missing platform-specific navigation patterns (tab bar position)
- Font rendering differences not accounted for (Android vs iOS)
- Status bar color not configured per platform
- Missing Android-specific features (hardware back button handling)
Best Practices - Code Quality
React Native Architecture
- Functional components with TypeScript → React Native Overview
- Custom hooks for device APIs (camera, location, permissions)
- Platform-specific code isolated in separate files (
.ios.ts,.android.ts) - Shared business logic, platform-specific UI when needed
- Feature-based folder structure
Performance
- Hermes enabled for production builds → React Native Overview - Performance
- FlatList for lists > 10 items
- Images optimized (webp format, appropriate sizes)
- react-native-fast-image for network images
- Native driver for animations (
useNativeDriver: true) - Code splitting with lazy loading for large features
- Bundle size monitoring
Security
- Keychain/Keystore for sensitive data → React Native Security
- Certificate pinning enabled
- ProGuard/R8 obfuscation for Android release builds
- Hermes bytecode for iOS obfuscation
- Jailbreak/root detection
- Disable logging in production builds
- Screen capture prevention for sensitive screens
Data & State
- React Query for server state (caching, background updates) → React Native Data
- Zustand for global client state
- AsyncStorage for non-sensitive persisted data
- Offline-first architecture for core features
- Optimistic updates for better UX
UI/UX
- SafeAreaView on iOS screens
- Platform-specific designs (Material You on Android, iOS HIG on iOS)
- Loading states for async operations
- Error states with retry actions
- Empty states for no data
- Pull-to-refresh on lists
- Haptic feedback for interactions
Navigation
- React Navigation (recommended) → React Native Navigation
- Deep linking configured
- Loading states during navigation
- Proper back button handling (Android)
- Tab bar navigator for bottom navigation
- Stack navigator for hierarchical navigation
Testing
- Unit tests for business logic and custom hooks → React Native Testing
- Integration tests with React Native Testing Library
- E2E tests with Detox for critical flows
- Visual regression tests for UI components
- Test on both platforms (iOS and Android)
- Test on multiple device sizes
Build Configuration
- Separate staging and production builds with different bundle IDs
- Environment-specific configuration (API URLs, keys)
- Proper versioning (semver)
- ProGuard rules for third-party libraries
- Bitcode disabled (deprecated by Apple)
- App signing configured correctly
Quick Scan Table
| Category | What to Check | Severity | Reference |
|---|---|---|---|
| Security | Keychain/Keystore for sensitive data | Block | Security |
| Security | Certificate pinning enabled | Block | Security |
| Security | No API keys in source code | Block | Security |
| Security | ProGuard/obfuscation enabled | Fix | Security |
| Performance | FlatList for long lists (not ScrollView) | Fix | Performance |
| Performance | Images optimized (webp, sized correctly) | Fix | Performance |
| Performance | Animations use native driver | Fix | Performance |
| GOOD: | Performance | Hermes enabled | Review |
| Platform | SafeAreaView on iOS | Fix | UI |
| Platform | Android back button handled | Fix | Navigation |
| GOOD: | Platform | Platform-specific code isolated | Review |
| Hooks | Event listeners cleaned up | Fix | React Checklist |
| Hooks | Dependencies complete in useEffect | Fix | React Checklist |
| Data | Offline support for critical features | Fix | Data |
| Data | Request timeouts configured | Fix | Data |
| GOOD: | Navigation | Deep linking configured | Review |
| GOOD: | Build | Staging and production builds separated | Review |
Legend:
- Block PR - Security vulnerability or critical mobile-specific bug
- Fix Before Merge - Performance issue, platform compatibility, or likely bug
- [GOOD] Review & Discuss - Code quality improvement
Additional Mobile Considerations
Device-Specific Issues
- Not testing on low-end Android devices (< 2GB RAM)
- Missing landscape orientation support when required
- No tablet layout for large screens
- Different screen densities not handled (mdpi, hdpi, xhdpi, xxhdpi)
- Notch/Dynamic Island not accounted for (iOS)
- Foldable device support missing when required (Android)
Permissions
- Permissions requested without user-facing explanation
- Missing permission rationale (iOS usage descriptions, Android permission dialogs)
- Not handling denied permissions gracefully
- Requesting permissions at app launch instead of when needed
- Missing permission checks before accessing protected APIs
Native Modules
- Custom native modules without TypeScript types
- Bridge calls in tight loops (performance issue)
- Not handling native module errors
- Missing null checks for optional native module responses
- Native module threading issues (calling UI thread from background)
Push Notifications
- No notification permission request flow
- Missing notification handler for foreground notifications
- Deep links from notifications not working
- Notification data not validated before processing
- No badge count management
App State Management
- Not handling app background/foreground transitions
- Sensitive data visible when app backgrounded (missing blur overlay)
- Timers not paused when app backgrounded
- Network requests not cancelled when backgrounded
- Missing state restoration after app termination
Accessibility
- Missing accessibility labels on interactive elements
- No screen reader support (VoiceOver, TalkBack)
- Minimum touch target size < 44x44 points
- Missing focus management for keyboard navigation
- No dynamic type support (font scaling)
Block Checklist - Must Fix Before Merge
- No sensitive data in AsyncStorage (use Keychain/Keystore)
- No API keys or secrets in source code
- Certificate pinning enabled for production
- ProGuard/R8 enabled for Android release
- No network calls on main thread
- Event listeners cleaned up on unmount
- FlatList used for long lists (not ScrollView)
- SafeAreaView used on iOS screens
- Android back button handled properly
- No infinite loops or memory leaks
Mobile-Specific Testing Checklist
Before approving mobile PRs, verify:
- Tested on both iOS and Android
- Tested on multiple screen sizes (small phone, large phone, tablet if applicable)
- Tested offline behavior
- Tested slow network (3G simulation)
- Tested app backgrounding and foregrounding
- Tested deep links
- Tested push notifications (if applicable)
- Tested permission flows (grant and deny scenarios)
- Checked memory usage (< 200MB for most screens)
- Checked bundle size impact
Related Documentation
React Native Guides:
- React Native Overview - Setup, configuration, tooling
- React Native Navigation - Navigation patterns
- React Native UI - Components, styling, platform UI
- React Native Data - API integration, offline, state
- React Native Security - Keychain, biometrics, pinning
- React Native Performance - Optimization strategies
Cross-Platform:
- React Code Review Checklist - Common React patterns
- Android Code Review Checklist - Native Android
- iOS Code Review Checklist - Native iOS
- TypeScript Guidelines
Process: