React Native Expert
Senior mobile engineer building production-ready cross-platform applications with React Native and Expo.
When to Use
- Building a new React Native or Expo mobile app from scratch
- Setting up navigation (tabs, stacks, drawers, deep linking)
- Integrating native modules or platform-specific code
- Optimizing list performance (FlatList, SectionList)
- Handling SafeArea, keyboard avoidance, or platform differences
- Debugging Metro bundler, Xcode, or Gradle build issues
- Configuring Expo SDK projects
Don't use when: Building web-only apps, native Swift/Objective-C iOS apps, or native Kotlin/Java Android apps — use the appropriate platform-specific skills instead.
Core Workflow
- Setup — Scaffold with Expo, configure TypeScript → run
npx expo doctor to verify environment and SDK compatibility; fix any reported issues before proceeding
- Structure — Organize by feature, set up routing (Expo Router or React Navigation)
- Implement — Build components with platform handling → verify on iOS simulator and Android emulator; check Metro bundler output for errors before moving on
- Optimize — Optimize lists, images, memory → profile with Flipper or React DevTools
- Test — Test on both platforms, prioritize real devices over simulators
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
Key Patterns
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>
));
const keyExtractor = (item: Item) => item.id;
export function ItemList({ data }: { data: Item[] }) {
const renderItem = useCallback(
({ item }: { item: Item }) => (
<ListItem title={item.title} => console.log(item.id)} />
),
[]
);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
removeClippedSubviews
maxToRenderPerBatch={10}
/>
);
}
const styles = StyleSheet.create({
item: { padding: 16, borderBottomWidth: 1, borderBottomColor: '#eee' },
});
SafeAreaView + Keyboard Avoidance
import React from 'react';
import { SafeAreaView, KeyboardAvoidingView, Platform, TextInput, StyleSheet } from 'react-native';
export function SafeForm() {
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.inner}
>
<TextInput placeholder="Enter text" style={styles.input} />
</KeyboardAvoidingView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff' },
inner: { padding: 16 },
input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12 },
});
Platform-Specific Code
import { Platform, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
...Platform.select({
ios: { shadowColor: '#000', shadowOpacity: 0.25, shadowRadius: 4 },
android: { elevation: 4 },
default: {},
}),
},
});
Constraints
MUST DO
- Use FlatList/SectionList for scrollable lists (never ScrollView for large data)
- Implement
memo + useCallback for list items to prevent unnecessary re-renders
- Wrap top-level content in
SafeAreaView for device notches and safe areas
- Use
KeyboardAvoidingView for forms and text input screens
- Handle Android back button behavior in navigation stacks
- Test on both iOS and Android — platform differences are common
- Use
npx expo install (not npm install) for native modules to ensure SDK compatibility
MUST NOT DO
- Use ScrollView for large or dynamic lists (causes memory and performance issues)
- Use inline styles extensively (creates new style objects every render)
- Hardcode dimensions (use flex, Dimensions API, or responsive helpers)
- Ignore memory leaks from event listeners and subscriptions
- Skip platform-specific testing — behavior differs between iOS and Android
- Use
waitFor/setTimeout for animations (use react-native-reanimated instead)
- Render heavy lists without
removeClippedSubviews or maxToRenderPerBatch
Project Setup Checklist
Performance Optimization
| Issue |
Solution |
| Janky scrolling |
Use FlatList with removeClippedSubviews, maxToRenderPerBatch |
| Slow re-renders |
Wrap components with memo, use useCallback for handlers |
| Image loading delays |
Use react-native-fast-image, implement caching |
| Navigation lag |
Lazy-load screens, defer heavy computations |
| Memory leaks |
Clean up subscriptions in cleanup functions, use useEffect return |
| Large bundle size |
Use @expo/config-plugins, tree-shake unused dependencies |
Cross-Team Integration
Related Skills: react-expert, flutter-expert, test-driven-development, systematic-debugging, mobile-code-impact-assessment
Used By: Any agent building mobile features, especially frontend engineers in DevForge AI or dedicated mobile engineering teams.
Source: Construct-AI-primary/z-docs-paperclip — distributed by TomeVault.
1---2name: construct-ai-primary-z-docs-paperclip-react-native-expert3description: React Native Expert4---56# React Native Expert78Senior mobile engineer building production-ready cross-platform applications with React Native and Expo.910## When to Use1112- Building a new React Native or Expo mobile app from scratch13- Setting up navigation (tabs, stacks, drawers, deep linking)14- Integrating native modules or platform-specific code15- Optimizing list performance (FlatList, SectionList)16- Handling SafeArea, keyboard avoidance, or platform differences17- Debugging Metro bundler, Xcode, or Gradle build issues18- Configuring Expo SDK projects1920**Don't use when:** Building web-only apps, native Swift/Objective-C iOS apps, or native Kotlin/Java Android apps — use the appropriate platform-specific skills instead.2122## Core Workflow23241. **Setup** — Scaffold with Expo, configure TypeScript → run `npx expo doctor` to verify environment and SDK compatibility; fix any reported issues before proceeding252. **Structure** — Organize by feature, set up routing (Expo Router or React Navigation)263. **Implement** — Build components with platform handling → verify on iOS simulator and Android emulator; check Metro bundler output for errors before moving on274. **Optimize** — Optimize lists, images, memory → profile with Flipper or React DevTools285. **Test** — Test on both platforms, prioritize real devices over simulators2930### Error Recovery3132- **Metro bundler errors** → Clear cache with `npx expo start --clear`, then restart33- **iOS build fails** → Check Xcode logs → resolve native dependency or provisioning issue → rebuild with `npx expo run:ios`34- **Android build fails** → Check `adb logcat` or Gradle output → resolve SDK/NDK version mismatch → rebuild with `npx expo run:android`35- **Native module not found** → Run `npx expo install <module>` to ensure compatible version, then rebuild native layers3637## Key Patterns3839### Optimized FlatList with memo + useCallback4041```tsx42import React, { memo, useCallback } from 'react';43import { FlatList, View, Text, StyleSheet } from 'react-native';4445type Item = { id: string; title: string };4647const ListItem = memo(({ title, onPress }: { title: string; onPress: () => void }) => (48 <View style={styles.item}>49 <Text onPress={onPress}>{title}</Text>50 </View>51));5253const keyExtractor = (item: Item) => item.id;5455export function ItemList({ data }: { data: Item[] }) {56 const renderItem = useCallback(57 ({ item }: { item: Item }) => (58 <ListItem title={item.title} onPress={() => console.log(item.id)} />59 ),60 []61 );6263 return (64 <FlatList65 data={data}66 renderItem={renderItem}67 keyExtractor={keyExtractor}68 removeClippedSubviews69 maxToRenderPerBatch={10}70 />71 );72}7374const styles = StyleSheet.create({75 item: { padding: 16, borderBottomWidth: 1, borderBottomColor: '#eee' },76});77```7879### SafeAreaView + Keyboard Avoidance8081```tsx82import React from 'react';83import { SafeAreaView, KeyboardAvoidingView, Platform, TextInput, StyleSheet } from 'react-native';8485export function SafeForm() {86 return (87 <SafeAreaView style={styles.container}>88 <KeyboardAvoidingView89 behavior={Platform.OS === 'ios' ? 'padding' : 'height'}90 style={styles.inner}91 >92 <TextInput placeholder="Enter text" style={styles.input} />93 </KeyboardAvoidingView>94 </SafeAreaView>95 );96}9798const styles = StyleSheet.create({99 container: { flex: 1, backgroundColor: '#fff' },100 inner: { padding: 16 },101 input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12 },102});103```104105### Platform-Specific Code106107```tsx108import { Platform, StyleSheet } from 'react-native';109110const styles = StyleSheet.create({111 container: {112 ...Platform.select({113 ios: { shadowColor: '#000', shadowOpacity: 0.25, shadowRadius: 4 },114 android: { elevation: 4 },115 default: {},116 }),117 },118});119```120121## Constraints122123### MUST DO124125- Use FlatList/SectionList for scrollable lists (never ScrollView for large data)126- Implement `memo` + `useCallback` for list items to prevent unnecessary re-renders127- Wrap top-level content in `SafeAreaView` for device notches and safe areas128- Use `KeyboardAvoidingView` for forms and text input screens129- Handle Android back button behavior in navigation stacks130- Test on both iOS and Android — platform differences are common131- Use `npx expo install` (not `npm install`) for native modules to ensure SDK compatibility132133### MUST NOT DO134135- Use ScrollView for large or dynamic lists (causes memory and performance issues)136- Use inline styles extensively (creates new style objects every render)137- Hardcode dimensions (use flex, Dimensions API, or responsive helpers)138- Ignore memory leaks from event listeners and subscriptions139- Skip platform-specific testing — behavior differs between iOS and Android140- Use `waitFor`/`setTimeout` for animations (use `react-native-reanimated` instead)141- Render heavy lists without `removeClippedSubviews` or `maxToRenderPerBatch`142143## Project Setup Checklist144145- [ ] Expo SDK version matches across `package.json` and native binaries146- [ ] `npx expo doctor` passes with no issues147- [ ] TypeScript configured with strict mode148- [ ] Navigation library chosen (Expo Router recommended for file-based routing)149- [ ] Platform-specific folders (`ios/`, `android/`) exist and build successfully150- [ ] ESLint + Prettier configured for `.tsx`/`.ts` files151- [ ] Metro config customized if needed (asset extensions, resolver config)152153## Performance Optimization154155| Issue | Solution |156|-------|----------|157| Janky scrolling | Use `FlatList` with `removeClippedSubviews`, `maxToRenderPerBatch` |158| Slow re-renders | Wrap components with `memo`, use `useCallback` for handlers |159| Image loading delays | Use `react-native-fast-image`, implement caching |160| Navigation lag | Lazy-load screens, defer heavy computations |161| Memory leaks | Clean up subscriptions in cleanup functions, use `useEffect` return |162| Large bundle size | Use `@expo/config-plugins`, tree-shake unused dependencies |163164## Cross-Team Integration165166**Related Skills:** `react-expert`, `flutter-expert`, `test-driven-development`, `systematic-debugging`, `mobile-code-impact-assessment`167168**Used By:** Any agent building mobile features, especially frontend engineers in DevForge AI or dedicated mobile engineering teams.169170---171> Source: [Construct-AI-primary/z-docs-paperclip](https://github.com/Construct-AI-primary/z-docs-paperclip) — distributed by [TomeVault](https://tomevault.io).172<!-- tomevault:4.0:skill_md:2026-05-22 -->