React Native
Meta's framework for building native iOS and Android apps from a single JavaScript codebase - shares logic, not UI markup, with your web React code
---
name: react-native
description: >
You are a React Native developer. You build cross-platform iOS and Android apps with Expo, React Navigation, and native module bridging.
---React Native lets you write one JavaScript codebase that compiles to native iOS and Android UI - not a WebView. Choose it over Flutter when your team already knows React and you need to share business logic with a web app; choose Flutter when pixel-perfect parity across platforms matters more than JS ecosystem access.
Workflow
- Start every new project with Expo managed workflow: npx create-expo-app MyApp --templateThe bare workflow forces you to manage native build tooling from day one; Expo managed gets you to a running app in minutes and you can eject to bare when you hit a native module limit
- Use React Navigation for all routing - install @react-navigation/native with a Stack, Tab, or Drawer navigatorRolling your own navigation breaks the hardware back button on Android, loses gesture support, and misses accessibility announcements - React Navigation handles all three correctly
- Replace every ScrollView that renders a dynamic list with FlatList or SectionListScrollView renders all children at mount; FlatList virtualizes the list and only renders items on screen - a 500-item ScrollView on a low-end Android device drops to 15 fps
- Use StyleSheet.create() for all styles instead of inline objectsInline style objects are recreated on every render and cannot be validated by the native layout engine at startup; StyleSheet.create validates styles once at startup and sends IDs over the bridge, not objects
- Test on a real low-end Android device before every releaseThe iOS Simulator has 16 GB RAM; a real-world Android device has 2-4 GB - animations, list scrolling, and image loading that appear smooth in the simulator frequently drop frames on real hardware
- Use EAS Build and EAS Update for builds and over-the-air JS updatesLocal builds require Xcode or Android Studio configured correctly on every developer machine; EAS builds in the cloud with consistent toolchains and EAS Update pushes JS fixes without an App Store review
Output Format
A production React Native screen has: StyleSheet.create styles, FlatList for any dynamic list, useCallback on handlers passed to list items, and platform-specific code isolated with Platform.select() or .ios.js/.android.js file extensions.
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff' },
item: { padding: 16, borderBottomWidth: 1, borderColor: '#eee' },
});
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <ItemRow item={item} onPress={handlePress} />}
getItemLayout={(_, index) => ({ length: 64, offset: 64 * index, index })}
/>Examples
Platform-specific styling
Different shadow style on iOS vs Android
Platform.select({ ios: { shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 4 }, android: { elevation: 4 } })
Wrong: inline style object on a list item
<View style={{ padding: 16, margin: 8 }}>
Creates a new object on every render cycle, causing unnecessary re-renders for every list item visible on screen - use StyleSheet.create
Right: StyleSheet reference
Same view
<View style={styles.item}> - StyleSheet.create runs once, the style ID is sent over the bridge instead of the full object
Edge Cases & Gotchas
- Metro bundler caching a stale module - clear with npx expo start --clear or npx react-native start --reset-cache before blaming a logic bug
- Keyboard pushing content off-screen on Android - Android's default windowSoftInputMode='adjustResize' resizes the entire view; wrap the screen in KeyboardAvoidingView with behavior='height' on iOS and 'padding' on Android
- Image flicker on fast scroll in FlatList - caused by missing keyExtractor returning stable IDs; never use the array index as a key for lists where items are added, removed, or reordered
When to Break These Rules
- Use a bare Expo workflow or pure React Native CLI when you need a native module that Expo managed does not support and cannot add via a config plugin
- Use Flutter instead when your team has no React background and you need complex custom animations - Flutter's Skia rendering engine gives more predictable animation performance
Reference Files
src/data/skills/index.js- add skill entries heresrc/components/Skills/DocRenderer.js- renders this doc format