$npx -y skills add Jeffallan/claude-skills --skill react-native-expertBuilds, 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 an
| 1 | # React Native Expert |
| 2 | |
| 3 | Senior mobile engineer building production-ready cross-platform applications with React Native and Expo. |
| 4 | |
| 5 | ## Core Workflow |
| 6 | |
| 7 | 1. **Setup** — Expo Router or React Navigation, TypeScript config → _run `npx expo doctor` to verify environment and SDK compatibility; fix any reported issues before proceeding_ |
| 8 | 2. **Structure** — Feature-based organization |
| 9 | 3. **Implement** — Components with platform handling → _verify on iOS simulator and Android emulator; check Metro bundler output for errors before moving on_ |
| 10 | 4. **Optimize** — FlatList, images, memory → _profile with Flipper or React DevTools_ |
| 11 | 5. **Test** — Both platforms, real devices |
| 12 | |
| 13 | ### Error Recovery |
| 14 | - **Metro bundler errors** → clear cache with `npx expo start --clear`, then restart |
| 15 | - **iOS build fails** → check Xcode logs → resolve native dependency or provisioning issue → rebuild with `npx expo run:ios` |
| 16 | - **Android build fails** → check `adb logcat` or Gradle output → resolve SDK/NDK version mismatch → rebuild with `npx expo run:android` |
| 17 | - **Native module not found** → run `npx expo install <module>` to ensure compatible version, then rebuild native layers |
| 18 | |
| 19 | ## Reference Guide |
| 20 | |
| 21 | Load detailed guidance based on context: |
| 22 | |
| 23 | | Topic | Reference | Load When | |
| 24 | |-------|-----------|-----------| |
| 25 | | Navigation | `references/expo-router.md` | Expo Router, tabs, stacks, deep linking | |
| 26 | | Platform | `references/platform-handling.md` | iOS/Android code, SafeArea, keyboard | |
| 27 | | Lists | `references/list-optimization.md` | FlatList, performance, memo | |
| 28 | | Storage | `references/storage-hooks.md` | AsyncStorage, MMKV, persistence | |
| 29 | | Structure | `references/project-structure.md` | Project setup, architecture | |
| 30 | |
| 31 | ## Constraints |
| 32 | |
| 33 | ### MUST DO |
| 34 | - Use FlatList/SectionList for lists (not ScrollView) |
| 35 | - Implement memo + useCallback for list items |
| 36 | - Handle SafeAreaView for notches |
| 37 | - Test on both iOS and Android real devices |
| 38 | - Use KeyboardAvoidingView for forms |
| 39 | - Handle Android back button in navigation |
| 40 | |
| 41 | ### MUST NOT DO |
| 42 | - Use ScrollView for large lists |
| 43 | - Use inline styles extensively (creates new objects) |
| 44 | - Hardcode dimensions (use Dimensions API or flex) |
| 45 | - Ignore memory leaks from subscriptions |
| 46 | - Skip platform-specific testing |
| 47 | - Use waitFor/setTimeout for animations (use Reanimated) |
| 48 | |
| 49 | ## Code Examples |
| 50 | |
| 51 | ### Optimized FlatList with memo + useCallback |
| 52 | |
| 53 | ```tsx |
| 54 | import React, { memo, useCallback } from 'react'; |
| 55 | import { FlatList, View, Text, StyleSheet } from 'react-native'; |
| 56 | |
| 57 | type Item = { id: string; title: string }; |
| 58 | |
| 59 | const ListItem = memo(({ title, onPress }: { title: string; onPress: () => void }) => ( |
| 60 | <View style={styles.item}> |
| 61 | <Text onPress={onPress}>{title}</Text> |
| 62 | </View> |
| 63 | )); |
| 64 | |
| 65 | export function ItemList({ data }: { data: Item[] }) { |
| 66 | const handlePress = useCallback((id: string) => { |
| 67 | console.log('pressed', id); |
| 68 | }, []); |
| 69 | |
| 70 | const renderItem = useCallback( |
| 71 | ({ item }: { item: Item }) => ( |
| 72 | <ListItem title={item.title} onPress={() => handlePress(item.id)} /> |
| 73 | ), |
| 74 | [handlePress] |
| 75 | ); |
| 76 | |
| 77 | return ( |
| 78 | <FlatList |
| 79 | data={data} |
| 80 | keyExtractor={(item) => item.id} |
| 81 | renderItem={renderItem} |
| 82 | removeClippedSubviews |
| 83 | maxToRenderPerBatch={10} |
| 84 | windowSize={5} |
| 85 | /> |
| 86 | ); |
| 87 | } |
| 88 | |
| 89 | const styles = StyleSheet.create({ |
| 90 | item: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth }, |
| 91 | }); |
| 92 | ``` |
| 93 | |
| 94 | ### KeyboardAvoidingView Form |
| 95 | |
| 96 | ```tsx |
| 97 | import React from 'react'; |
| 98 | import { |
| 99 | KeyboardAvoidingView, |
| 100 | Platform, |
| 101 | ScrollView, |
| 102 | TextInput, |
| 103 | StyleSheet, |
| 104 | SafeAreaView, |
| 105 | } from 'react-native'; |
| 106 | |
| 107 | export function LoginForm() { |
| 108 | return ( |
| 109 | <SafeAreaView style={styles.safe}> |
| 110 | <KeyboardAvoidingView |
| 111 | style={styles.flex} |
| 112 | behavior={Platform.OS === 'ios' ? 'padding' : 'height'} |
| 113 | > |
| 114 | <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled"> |
| 115 | <TextInput style={styles.input} placeholder="Email" autoCapitalize="none" /> |
| 116 | <TextInput style={styles.input} placeholder="Password" secureTextEntry /> |
| 117 | </ScrollView> |
| 118 | </KeyboardAvoidingView> |
| 119 | </SafeAreaView> |
| 120 | ); |
| 121 | } |
| 122 | |
| 123 | const styles = StyleSheet.create({ |
| 124 | safe: { flex: 1 }, |
| 125 | flex: { flex: 1 }, |
| 126 | co |