--- name: React Native Expert description: Expert in React Native for building cross-platform mobile applications. Use when working with React Native, Expo, mobile development, native modules, navigation, or when the user mentions React Native, mobile apps, iOS, Android, Expo, or cross-platform development. --- # React Native Expert A specialized skill for building production-ready cross-platform mobile applications with React Native and Expo. ## Instructions ### Core Workflow 1. **Understand requirements** - Identify if using Expo or bare React Native - Determine platform-specific needs (iOS/Android) - Understand navigation requirements - Identify native module needs 2. **Project setup** - Choose between Expo and bare React Native - Set up navigation (React Navigation) - Configure TypeScript - Set up state management 3. **Implement features** - Create reusable components - Implement platform-specific code when needed - Handle device capabilities (camera, location, etc.) - Optimize performance for mobile 4. **Testing and deployment** - Test on both iOS and Android - Optimize app size and performance - Configure app deployment (App Store, Google Play) ### React Native Project Structure (Expo) ``` myapp/ ├── app/ # App directory (Expo Router) │ ├── (tabs)/ │ │ ├── index.tsx │ │ └── profile.tsx │ ├── _layout.tsx │ └── +not-found.tsx ├── components/ │ ├── common/ │ └── features/ ├── hooks/ │ ├── useAuth.ts │ └── useAsync.ts ├── services/ │ └── api.ts ├── constants/ │ ├── Colors.ts │ └── Layout.ts ├── utils/ │ └── storage.ts ├── types/ │ └── index.ts ├── app.json └── package.json ``` ### Component Patterns ```typescript import { View, Text, StyleSheet, Platform, Pressable } from 'react-native'; import { FC } from 'react'; interface ButtonProps { title: string; onPress: () => void; variant?: 'primary' | 'secondary'; disabled?: boolean; } export const Button: FC = ({ title, onPress, variant = 'primary', disabled = false, }) => { return ( [ styles.button, variant === 'primary' ? styles.primaryButton : styles.secondaryButton, pressed && styles.pressed, disabled && styles.disabled, ]} > {title} ); }; const styles = StyleSheet.create({ button: { paddingVertical: 12, paddingHorizontal: 24, borderRadius: 8, alignItems: 'center', justifyContent: 'center', ...Platform.select({ ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84, }, android: { elevation: 5, }, }), }, primaryButton: { backgroundColor: '#007AFF', }, secondaryButton: { backgroundColor: '#E5E5EA', }, pressed: { opacity: 0.7, }, disabled: { opacity: 0.5, }, text: { fontSize: 16, fontWeight: '600', }, primaryText: { color: '#FFFFFF', }, secondaryText: { color: '#000000', }, }); ``` ### Navigation (React Navigation) ```typescript // app/_layout.tsx (Expo Router) import { Stack } from 'expo-router'; export default function RootLayout() { return ( ); } // Or with React Navigation import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; type RootStackParamList = { Home: undefined; Profile: { userId: string }; Details: { itemId: number }; }; const Stack = createNativeStackNavigator(); export default function App() { return ( ); } // Type-safe navigation import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useNavigation } from '@react-navigation/native'; type ProfileScreenNavigationProp = NativeStackNavigationProp< RootStackParamList, 'Profile' >; const ProfileScreen = () => { const navigation = useNavigation(); const handlePress = () => { navigation.navigate('Details', { itemId: 42 }); }; return