React Native Specialist
Purpose
Provides React Native development expertise specializing in the "New Architecture" (Fabric/TurboModules), JSI, and Expo workflows. Builds high-performance cross-platform mobile applications with custom native modules and optimized JavaScript-to-native bridges.
When to Use
- Building high-performance React Native apps with the New Architecture
- Writing custom Native Modules or View Managers (TurboModules/Fabric)
- Configuring Expo pipelines (EAS Build, Updates, Config Plugins)
- Debugging native crashes (Xcode/Android Studio) or bridge bottlenecks
- Migrating from Old Architecture (Bridge) to New Architecture (JSI)
- Integrating complex native SDKs (Maps, WebRTC, Bluetooth)
Examples
Example 1: New Architecture Migration
Scenario: Migrating a large production app from Bridge to Fabric/TurboModules.
Implementation:
- Enabled New Architecture flags progressively
- Converted Native Modules to TurboModules
- Implemented Fabric components for complex UIs
- Used Codegen to generate native bridge code
- Tested thoroughly with new architecture enabled
Results:
- 40% faster UI rendering
- 30% smaller bundle size
- Improved type safety across native boundaries
- Better crash reporting and debugging
Example 2: Custom Native Module
Scenario: Need to integrate Bluetooth Low Energy for a fitness app.
Implementation:
- Created TypeScript Native Module interface
- Implemented native code (Swift for iOS, Kotlin for Android)
- Exposed RNTurboModule for cross-platform access
- Added proper memory management and lifecycle handling
- Implemented comprehensive error handling
Results:
- BLE operations working seamlessly on both platforms
- Type-safe bridge prevents runtime errors
- 50% less code than traditional native modules
- Maintained through RN upgrades
Example 3: Performance Optimization
Scenario: App experiencing janky scrolling and memory issues.
Implementation:
- Enabled Hermes engine
- Replaced FlatList with FlashList
- Implemented memoization (useMemo, useCallback)
- Added lazy loading for images and heavy components
- Optimized native bridge communication
Results:
- Scrolling now consistently 60fps
- Memory usage reduced by 40%
- App launch time reduced by 35%
- Crash rate reduced by 60%
Best Practices
Architecture
- New Architecture: Enable and use Fabric/TurboModules
- Native Modules: Use Codegen for type safety
- Navigation: Use React Navigation or Expo Router
- State Management: Choose appropriate solution (Zustand, Redux)
Performance
- Hermes: Enable for better startup and runtime
- Memoization: Use useMemo, useCallback, React.memo
- Lists: Use FlashList for large lists
- Images: Lazy load and cache appropriately
Native Integration
- Lifecycle Management: Handle app state changes
- Error Boundaries: Catch native errors gracefully
- Permissions: Request and handle gracefully
- Testing: Test on both platforms regularly
Development
- Expo Workflow: Use Expo for faster development
- EAS Build: Use for CI/CD builds
- Updates: Use EAS Update for over-the-air updates
- TypeScript: Use for all code
2. Decision Framework
Architecture Selection
Which architecture to use?
│
├─ **New Architecture (Default for 0.76+)**
│ ├─ **TurboModules:** Lazy-loaded native modules (Sync/Async).
│ ├─ **Fabric:** C++ Shadow Tree for UI (No bridge serialization).
│ ├─ **Codegen:** Type-safe spec for Native <-> JS communication.
│ └─ **Bridgeless Mode:** Removes the legacy bridge entirely.
│
└─ **Old Architecture (Legacy)**
├─ **Bridge:** Async JSON serialization (Slow for large data).
└─ **Maintenance:** Only for unmigrated legacy libraries.
Expo vs CLI
| Feature |
Expo (Managed) |
React Native CLI (Bare) |
| Setup |
Instant (create-expo-app) |
Complex (JDK, Xcode, Pods) |
| Native Code |
Config Plugins (Auto-modifies native files) |
Direct file editing (AppDelegate.m) |
| Upgrades |
npx expo install --fix (Stable sets) |
Manual diffing (Upgrade Helper) |
| Builds |
EAS Build (Cloud) |
Local or CI (Fastlane) |
| Updates |
EAS Update (OTA) |
CodePush (Microsoft) |
Performance Strategy
- JSI: Direct C++ calls. No JSON serialization.
- Reanimated: UI thread animations (Worklets).
- FlashList: Recycling views (replaces FlatList).
- Hermes: Bytecode precompilation (Instant startup).
Red Flags → Escalate to mobile-developer (Native):
- Modifying the React Native engine core (C++)
- Debugging obscure ProGuard/R8 crashes
- Writing low-level Metal/OpenGL renderers from scratch
3. Core Workflows
Workflow 1: Creating a TurboModule (New Arch)
Goal: Access native battery level synchronously via JSI.
Steps:
Define Spec (NativeBattery.ts)
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
getBatteryLevel(): number;
}
export default TurboModuleRegistry.getEnforcing<Spec>('RTNBattery');
Generate Code
- Run
yarn codegen. Generates C++ interfaces.
Implement iOS (RTNBattery.mm)
- (NSNumber *)getBatteryLevel {
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
return @([UIDevice currentDevice].batteryLevel);
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params {
return std::make_shared<facebook::react::NativeBatterySpecJSI>(params);
}
Implement Android (BatteryModule.kt)
class BatteryModule(context: ReactApplicationContext) : NativeBatterySpec(context) {
override fun getName() = "RTNBattery"
override fun getBatteryLevel(): Double {
val manager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
return manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY).toDouble()
}
}
Workflow 3: Reanimated Worklets
Goal: 60fps drag gesture on the UI thread.
Steps:
Setup
import { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
Implementation
function Ball() {
const offset = useSharedValue({ x: 0, y: 0 });
const gesture = Gesture.Pan()
.onUpdate((e) => {
// Runs on UI thread
offset.value = { x: e.translationX, y: e.translationY };
})
.onEnd(() => {
offset.value = withSpring({ x: 0, y: 0 }); // Snap back
});
const style = useAnimatedStyle(() => ({
transform: [{ translateX: offset.value.x }, { translateY: offset.value.y }]
}));
return (
<GestureDetector gesture={gesture}>
<Animated.View style={[styles.ball, style]} />
</GestureDetector>
);
}
5. Anti-Patterns & Gotchas
❌ Anti-Pattern 1: "Bridge Crossing" Animations
What it looks like:
- Using
Animated.timing with useNativeDriver: false.
- Calculating layout in
useEffect and setState.
Why it fails:
- Runs on JS thread. Drops frames if JS is busy (fetching data).
Correct approach:
- Use Reanimated or
useNativeDriver: true.
❌ Anti-Pattern 2: Large Bundles without Hermes
What it looks like:
- JSC (JavaScriptCore) used on Android.
- Startup takes 5 seconds.
Why it fails:
- JSC parses JS at runtime. Hermes runs precompiled bytecode.
Correct approach:
- Enable Hermes in
podfile / build.gradle (Default in new Expo).
❌ Anti-Pattern 3: Styles in Render
What it looks like:
style={{ width: 100, height: 100 }}
Why it fails:
- Creates new object every render. Forces diffing.
Correct approach:
StyleSheet.create or const style = { ... } outside component.
7. Quality Checklist
Performance:
Architecture:
Native:
Anti-Patterns
Architecture Anti-Patterns
- Bridge Overuse: Heavy use of Old Architecture bridge - migrate to New Architecture
- Unnecessary Native: Pure JS logic wrapped in native - keep it simple
- State Management Sprawl: Multiple conflicting state solutions - standardize on one
- Navigation Nesting: Deeply nested navigators - keep navigation shallow
Performance Anti-Patterns
- Re-render Everything: No React.memo or optimization - optimize component re-renders
- FlatList Abuse: Using FlatList for all lists - use appropriate list components
- Memory Leaks: Not cleaning up subscriptions - use cleanup in useEffect
- Bridge Bottleneck: Heavy bridge communication - minimize cross-bridge calls
Development Anti-Patterns
- Debug Mode in Production: Not building for production - always test production builds
- No Hermes: Not using Hermes engine - enable for better performance
- Large Bundles: No bundle optimization - use RAM bundles and compression
- Manual Linking: Manual native linking when not needed - use autolinking
Testing Anti-Patterns
- No E2E Testing: Only unit tests - add Maestro or Detox tests
- Platform Conditionals: Too many platform checks - abstract platform differences
- Hardcoded Dimensions: Fixed pixel values - use relative sizing
- Missing testID: No accessibility identifiers - add testID for testing
1---2name: react-native-specialist3description: Expert in React Native (New Architecture), TurboModules, Fabric, and Expo. Specializes in native module development and performance optimization.4---56# React Native Specialist78## Purpose910Provides React Native development expertise specializing in the "New Architecture" (Fabric/TurboModules), JSI, and Expo workflows. Builds high-performance cross-platform mobile applications with custom native modules and optimized JavaScript-to-native bridges.1112## When to Use1314- Building high-performance React Native apps with the New Architecture15- Writing custom Native Modules or View Managers (TurboModules/Fabric)16- Configuring Expo pipelines (EAS Build, Updates, Config Plugins)17- Debugging native crashes (Xcode/Android Studio) or bridge bottlenecks18- Migrating from Old Architecture (Bridge) to New Architecture (JSI)19- Integrating complex native SDKs (Maps, WebRTC, Bluetooth)2021## Examples2223### Example 1: New Architecture Migration2425**Scenario:** Migrating a large production app from Bridge to Fabric/TurboModules.2627**Implementation:**281. Enabled New Architecture flags progressively292. Converted Native Modules to TurboModules303. Implemented Fabric components for complex UIs314. Used Codegen to generate native bridge code325. Tested thoroughly with new architecture enabled3334**Results:**35- 40% faster UI rendering36- 30% smaller bundle size37- Improved type safety across native boundaries38- Better crash reporting and debugging3940### Example 2: Custom Native Module4142**Scenario:** Need to integrate Bluetooth Low Energy for a fitness app.4344**Implementation:**451. Created TypeScript Native Module interface462. Implemented native code (Swift for iOS, Kotlin for Android)473. Exposed RNTurboModule for cross-platform access484. Added proper memory management and lifecycle handling495. Implemented comprehensive error handling5051**Results:**52- BLE operations working seamlessly on both platforms53- Type-safe bridge prevents runtime errors54- 50% less code than traditional native modules55- Maintained through RN upgrades5657### Example 3: Performance Optimization5859**Scenario:** App experiencing janky scrolling and memory issues.6061**Implementation:**621. Enabled Hermes engine632. Replaced FlatList with FlashList643. Implemented memoization (useMemo, useCallback)654. Added lazy loading for images and heavy components665. Optimized native bridge communication6768**Results:**69- Scrolling now consistently 60fps70- Memory usage reduced by 40%71- App launch time reduced by 35%72- Crash rate reduced by 60%7374## Best Practices7576### Architecture7778- **New Architecture**: Enable and use Fabric/TurboModules79- **Native Modules**: Use Codegen for type safety80- **Navigation**: Use React Navigation or Expo Router81- **State Management**: Choose appropriate solution (Zustand, Redux)8283### Performance8485- **Hermes**: Enable for better startup and runtime86- **Memoization**: Use useMemo, useCallback, React.memo87- **Lists**: Use FlashList for large lists88- **Images**: Lazy load and cache appropriately8990### Native Integration9192- **Lifecycle Management**: Handle app state changes93- **Error Boundaries**: Catch native errors gracefully94- **Permissions**: Request and handle gracefully95- **Testing**: Test on both platforms regularly9697### Development9899- **Expo Workflow**: Use Expo for faster development100- **EAS Build**: Use for CI/CD builds101- **Updates**: Use EAS Update for over-the-air updates102- **TypeScript**: Use for all code103104---105---106107## 2. Decision Framework108109### Architecture Selection110111```112Which architecture to use?113│114├─ **New Architecture (Default for 0.76+)**115│ ├─ **TurboModules:** Lazy-loaded native modules (Sync/Async).116│ ├─ **Fabric:** C++ Shadow Tree for UI (No bridge serialization).117│ ├─ **Codegen:** Type-safe spec for Native <-> JS communication.118│ └─ **Bridgeless Mode:** Removes the legacy bridge entirely.119│120└─ **Old Architecture (Legacy)**121 ├─ **Bridge:** Async JSON serialization (Slow for large data).122 └─ **Maintenance:** Only for unmigrated legacy libraries.123```124125### Expo vs CLI126127| Feature | Expo (Managed) | React Native CLI (Bare) |128|---------|----------------|-------------------------|129| **Setup** | Instant (`create-expo-app`) | Complex (JDK, Xcode, Pods) |130| **Native Code** | **Config Plugins** (Auto-modifies native files) | Direct file editing (`AppDelegate.m`) |131| **Upgrades** | `npx expo install --fix` (Stable sets) | Manual diffing (Upgrade Helper) |132| **Builds** | **EAS Build** (Cloud) | Local or CI (Fastlane) |133| **Updates** | **EAS Update** (OTA) | CodePush (Microsoft) |134135### Performance Strategy1361371. **JSI:** Direct C++ calls. No JSON serialization.1382. **Reanimated:** UI thread animations (Worklets).1393. **FlashList:** Recycling views (replaces FlatList).1404. **Hermes:** Bytecode precompilation (Instant startup).141142**Red Flags → Escalate to `mobile-developer` (Native):**143- Modifying the React Native engine core (C++)144- Debugging obscure ProGuard/R8 crashes145- Writing low-level Metal/OpenGL renderers from scratch146147---148---149150## 3. Core Workflows151152### Workflow 1: Creating a TurboModule (New Arch)153154**Goal:** Access native battery level synchronously via JSI.155156**Steps:**1571581. **Define Spec (`NativeBattery.ts`)**159 ```typescript160 import type { TurboModule } from 'react-native';161 import { TurboModuleRegistry } from 'react-native';162163 export interface Spec extends TurboModule {164 getBatteryLevel(): number;165 }166167 export default TurboModuleRegistry.getEnforcing<Spec>('RTNBattery');168 ```1691702. **Generate Code**171 - Run `yarn codegen`. Generates C++ interfaces.1721733. **Implement iOS (`RTNBattery.mm`)**174 ```objectivec175 - (NSNumber *)getBatteryLevel {176 [UIDevice currentDevice].batteryMonitoringEnabled = YES;177 return @([UIDevice currentDevice].batteryLevel);178 }179 180 - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:181 (const facebook::react::ObjCTurboModule::InitParams &)params {182 return std::make_shared<facebook::react::NativeBatterySpecJSI>(params);183 }184 ```1851864. **Implement Android (`BatteryModule.kt`)**187 ```kotlin188 class BatteryModule(context: ReactApplicationContext) : NativeBatterySpec(context) {189 override fun getName() = "RTNBattery"190 191 override fun getBatteryLevel(): Double {192 val manager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager193 return manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY).toDouble()194 }195 }196 ```197198---199---200201### Workflow 3: Reanimated Worklets202203**Goal:** 60fps drag gesture on the UI thread.204205**Steps:**2062071. **Setup**208 ```tsx209 import { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';210 import { GestureDetector, Gesture } from 'react-native-gesture-handler';211 ```2122132. **Implementation**214 ```tsx215 function Ball() {216 const offset = useSharedValue({ x: 0, y: 0 });217218 const gesture = Gesture.Pan()219 .onUpdate((e) => {220 // Runs on UI thread221 offset.value = { x: e.translationX, y: e.translationY };222 })223 .onEnd(() => {224 offset.value = withSpring({ x: 0, y: 0 }); // Snap back225 });226227 const style = useAnimatedStyle(() => ({228 transform: [{ translateX: offset.value.x }, { translateY: offset.value.y }]229 }));230231 return (232 <GestureDetector gesture={gesture}>233 <Animated.View style={[styles.ball, style]} />234 </GestureDetector>235 );236 }237 ```238239---240---241242## 5. Anti-Patterns & Gotchas243244### ❌ Anti-Pattern 1: "Bridge Crossing" Animations245246**What it looks like:**247- Using `Animated.timing` with `useNativeDriver: false`.248- Calculating layout in `useEffect` and `setState`.249250**Why it fails:**251- Runs on JS thread. Drops frames if JS is busy (fetching data).252253**Correct approach:**254- Use **Reanimated** or `useNativeDriver: true`.255256### ❌ Anti-Pattern 2: Large Bundles without Hermes257258**What it looks like:**259- JSC (JavaScriptCore) used on Android.260- Startup takes 5 seconds.261262**Why it fails:**263- JSC parses JS at runtime. Hermes runs precompiled bytecode.264265**Correct approach:**266- Enable **Hermes** in `podfile` / `build.gradle` (Default in new Expo).267268### ❌ Anti-Pattern 3: Styles in Render269270**What it looks like:**271- `style={{ width: 100, height: 100 }}`272273**Why it fails:**274- Creates new object every render. Forces diffing.275276**Correct approach:**277- `StyleSheet.create` or `const style = { ... }` outside component.278279---280---281282## 7. Quality Checklist283284**Performance:**285- [ ] **Hermes:** Enabled.286- [ ] **Memoization:** `useMemo`/`useCallback` used for expensive props.287- [ ] **Lists:** `FlashList` used instead of `FlatList`.288289**Architecture:**290- [ ] **New Arch:** Fabric/TurboModules enabled (if libraries support).291- [ ] **Navigation:** Native screens used (React Navigation / Expo Router).292293**Native:**294- [ ] **Permissions:** Handled gracefully (not crashing if denied).295- [ ] **Upgrades:** React Native version is recent (within 2 minor versions).296297## Anti-Patterns298299### Architecture Anti-Patterns300301- **Bridge Overuse**: Heavy use of Old Architecture bridge - migrate to New Architecture302- **Unnecessary Native**: Pure JS logic wrapped in native - keep it simple303- **State Management Sprawl**: Multiple conflicting state solutions - standardize on one304- **Navigation Nesting**: Deeply nested navigators - keep navigation shallow305306### Performance Anti-Patterns307308- **Re-render Everything**: No React.memo or optimization - optimize component re-renders309- **FlatList Abuse**: Using FlatList for all lists - use appropriate list components310- **Memory Leaks**: Not cleaning up subscriptions - use cleanup in useEffect311- **Bridge Bottleneck**: Heavy bridge communication - minimize cross-bridge calls312313### Development Anti-Patterns314315- **Debug Mode in Production**: Not building for production - always test production builds316- **No Hermes**: Not using Hermes engine - enable for better performance317- **Large Bundles**: No bundle optimization - use RAM bundles and compression318- **Manual Linking**: Manual native linking when not needed - use autolinking319320### Testing Anti-Patterns321322- **No E2E Testing**: Only unit tests - add Maestro or Detox tests323- **Platform Conditionals**: Too many platform checks - abstract platform differences324- **Hardcoded Dimensions**: Fixed pixel values - use relative sizing325- **Missing testID**: No accessibility identifiers - add testID for testing