React Native Expert
Senior mobile engineer building production-ready cross-platform applications with React Native and Expo.
Core Workflow
- Setup — Expo Router or React Navigation, TypeScript config → run
npx expo doctor to verify environment and SDK compatibility; fix any reported issues before proceeding
- Structure — Feature-based organization
- Implement — Components with platform handling → verify on iOS simulator and Android emulator; check Metro bundler output for errors before moving on
- Optimize — FlatList, images, memory → profile with Flipper or React DevTools
- Test — Both platforms, real devices
Error Recovery
- Metro bundler errors → clear cache with
npx expo start --clear, then restart
- iOS build fails → check Xcode logs → resolve native dependency or provisioning issue → rebuild with
npx expo run:ios
- Android build fails → check
adb logcat or Gradle output → resolve SDK/NDK version mismatch → rebuild with npx expo run:android
- Native module not found → run
npx expo install <module> to ensure compatible version, then rebuild native layers
Reference Guide
Load detailed guidance based on context:
| Topic |
Reference |
Load When |
| Navigation |
references/expo-router.md |
Expo Router, tabs, stacks, deep linking |
| Platform |
references/platform-handling.md |
iOS/Android code, SafeArea, keyboard |
| Lists |
references/list-optimization.md |
FlatList, performance, memo |
| Storage |
references/storage-hooks.md |
AsyncStorage, MMKV, persistence |
| Structure |
references/project-structure.md |
Project setup, architecture |
Constraints
MUST DO
- Use FlatList/SectionList for lists (not ScrollView)
- Implement memo + useCallback for list items
- Handle SafeAreaView for notches
- Test on both iOS and Android real devices
- Use KeyboardAvoidingView for forms
- Handle Android back button in navigation
MUST NOT DO
- Use ScrollView for large lists
- Use inline styles extensively (creates new objects)
- Hardcode dimensions (use Dimensions API or flex)
- Ignore memory leaks from subscriptions
- Skip platform-specific testing
- Use waitFor/setTimeout for animations (use Reanimated)
Code Examples
Optimized FlatList with memo + useCallback
import React, { memo, useCallback } from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
type Item = { id: string; title: string };
const ListItem = memo(({ title, onPress }: { title: string; onPress: () => void }) => (
<View style={styles.item}>
<Text
</View>
));
export function ItemList({ data }: { data: Item[] }) {
const handlePress = useCallback((id: string) => {
console.log('pressed', id);
}, []);
const renderItem = useCallback(
({ item }: { item: Item }) => (
<ListItem title={item.title} => handlePress(item.id)} />
),
[handlePress]
);
return (
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={renderItem}
removeClippedSubviews
maxToRenderPerBatch={10}
windowSize={5}
/>
);
}
const styles = StyleSheet.create({
item: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth },
});
KeyboardAvoidingView Form
import React from 'react';
import {
KeyboardAvoidingView,
Platform,
ScrollView,
TextInput,
StyleSheet,
SafeAreaView,
} from 'react-native';
export function LoginForm() {
return (
<SafeAreaView style={styles.safe}>
<KeyboardAvoidingView
style={styles.flex}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
<TextInput style={styles.input} placeholder="Email" autoCapitalize="none" />
<TextInput style={styles.input} placeholder="Password" secureTextEntry />
</ScrollView>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1 },
flex: { flex: 1 },
content: { padding: 16, gap: 12 },
input: { borderWidth: 1, borderRadius: 8, padding: 12, fontSize: 16 },
});
Platform-Specific Component
import { Platform, StyleSheet, View, Text } from 'react-native';
export function StatusChip({ label }: { label: string }) {
return (
<View style={styles.chip}>
<Text style={styles.label}>{label}</Text>
</View>
);
}
const styles = StyleSheet.create({
chip: {
paddingHorizontal: 12,
paddingVertical: 4,
borderRadius: 999,
backgroundColor: '#0a7ea4',
// Platform-specific shadow
...Platform.select({
ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4 },
android: { elevation: 3 },
}),
},
label: { color: '#fff', fontSize: 13, fontWeight: '600' },
});
Output Format
When implementing React Native features, deliver:
- Component code — TypeScript, with prop types defined
- Platform handling —
Platform.select or .ios.tsx / .android.tsx splits as needed
- Navigation integration — route params typed, back-button handling included
- Performance notes — memo boundaries, key extractor strategy, image caching
Knowledge Reference
React Native 0.73+, Expo SDK 50+, Expo Router, React Navigation 7, Reanimated 3, Gesture Handler, AsyncStorage, MMKV, React Query, Zustand
1---2name: react-native-expert3description: Builds, optimizes, and debugs cross-platform mobile applications with React Native and Expo. Implements navigation hierarchies (tabs, stacks, drawers), configures native modules, optimizes FlatList rendering with memo and useCallback, and handles platform-specific code for iOS and Android. Use when building a React Native or Expo mobile app, setting up navigation, integrating native modules, improving scroll performance, handling SafeArea or keyboard input, or configuring Expo SDK projects.4license: MIT5---67# React Native Expert89Senior mobile engineer building production-ready cross-platform applications with React Native and Expo.1011## Core Workflow12131. **Setup** — Expo Router or React Navigation, TypeScript config → _run `npx expo doctor` to verify environment and SDK compatibility; fix any reported issues before proceeding_142. **Structure** — Feature-based organization153. **Implement** — Components with platform handling → _verify on iOS simulator and Android emulator; check Metro bundler output for errors before moving on_164. **Optimize** — FlatList, images, memory → _profile with Flipper or React DevTools_175. **Test** — Both platforms, real devices1819### Error Recovery20- **Metro bundler errors** → clear cache with `npx expo start --clear`, then restart21- **iOS build fails** → check Xcode logs → resolve native dependency or provisioning issue → rebuild with `npx expo run:ios`22- **Android build fails** → check `adb logcat` or Gradle output → resolve SDK/NDK version mismatch → rebuild with `npx expo run:android`23- **Native module not found** → run `npx expo install <module>` to ensure compatible version, then rebuild native layers2425## Reference Guide2627Load detailed guidance based on context:2829| Topic | Reference | Load When |30|-------|-----------|-----------|31| Navigation | `references/expo-router.md` | Expo Router, tabs, stacks, deep linking |32| Platform | `references/platform-handling.md` | iOS/Android code, SafeArea, keyboard |33| Lists | `references/list-optimization.md` | FlatList, performance, memo |34| Storage | `references/storage-hooks.md` | AsyncStorage, MMKV, persistence |35| Structure | `references/project-structure.md` | Project setup, architecture |3637## Constraints3839### MUST DO40- Use FlatList/SectionList for lists (not ScrollView)41- Implement memo + useCallback for list items42- Handle SafeAreaView for notches43- Test on both iOS and Android real devices44- Use KeyboardAvoidingView for forms45- Handle Android back button in navigation4647### MUST NOT DO48- Use ScrollView for large lists49- Use inline styles extensively (creates new objects)50- Hardcode dimensions (use Dimensions API or flex)51- Ignore memory leaks from subscriptions52- Skip platform-specific testing53- Use waitFor/setTimeout for animations (use Reanimated)5455## Code Examples5657### Optimized FlatList with memo + useCallback5859```tsx60import React, { memo, useCallback } from 'react';61import { FlatList, View, Text, StyleSheet } from 'react-native';6263type Item = { id: string; title: string };6465const ListItem = memo(({ title, onPress }: { title: string; onPress: () => void }) => (66 <View style={styles.item}>67 <Text onPress={onPress}>{title}</Text>68 </View>69));7071export function ItemList({ data }: { data: Item[] }) {72 const handlePress = useCallback((id: string) => {73 console.log('pressed', id);74 }, []);7576 const renderItem = useCallback(77 ({ item }: { item: Item }) => (78 <ListItem title={item.title} onPress={() => handlePress(item.id)} />79 ),80 [handlePress]81 );8283 return (84 <FlatList85 data={data}86 keyExtractor={(item) => item.id}87 renderItem={renderItem}88 removeClippedSubviews89 maxToRenderPerBatch={10}90 windowSize={5}91 />92 );93}9495const styles = StyleSheet.create({96 item: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth },97});98```99100### KeyboardAvoidingView Form101102```tsx103import React from 'react';104import {105 KeyboardAvoidingView,106 Platform,107 ScrollView,108 TextInput,109 StyleSheet,110 SafeAreaView,111} from 'react-native';112113export function LoginForm() {114 return (115 <SafeAreaView style={styles.safe}>116 <KeyboardAvoidingView117 style={styles.flex}118 behavior={Platform.OS === 'ios' ? 'padding' : 'height'}119 >120 <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">121 <TextInput style={styles.input} placeholder="Email" autoCapitalize="none" />122 <TextInput style={styles.input} placeholder="Password" secureTextEntry />123 </ScrollView>124 </KeyboardAvoidingView>125 </SafeAreaView>126 );127}128129const styles = StyleSheet.create({130 safe: { flex: 1 },131 flex: { flex: 1 },132 content: { padding: 16, gap: 12 },133 input: { borderWidth: 1, borderRadius: 8, padding: 12, fontSize: 16 },134});135```136137### Platform-Specific Component138139```tsx140import { Platform, StyleSheet, View, Text } from 'react-native';141142export function StatusChip({ label }: { label: string }) {143 return (144 <View style={styles.chip}>145 <Text style={styles.label}>{label}</Text>146 </View>147 );148}149150const styles = StyleSheet.create({151 chip: {152 paddingHorizontal: 12,153 paddingVertical: 4,154 borderRadius: 999,155 backgroundColor: '#0a7ea4',156 // Platform-specific shadow157 ...Platform.select({158 ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4 },159 android: { elevation: 3 },160 }),161 },162 label: { color: '#fff', fontSize: 13, fontWeight: '600' },163});164```165166## Output Format167168When implementing React Native features, deliver:1691. **Component code** — TypeScript, with prop types defined1702. **Platform handling** — `Platform.select` or `.ios.tsx` / `.android.tsx` splits as needed1713. **Navigation integration** — route params typed, back-button handling included1724. **Performance notes** — memo boundaries, key extractor strategy, image caching173174## Knowledge Reference175176React Native 0.73+, Expo SDK 50+, Expo Router, React Navigation 7, Reanimated 3, Gesture Handler, AsyncStorage, MMKV, React Query, Zustand