Mobile Development6 min read

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

iOSAndroidJavaScriptCross-platformExpo
---
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

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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

Input

Different shadow style on iOS vs Android

Output

Platform.select({ ios: { shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 4 }, android: { elevation: 4 } })

Wrong: inline style object on a list item

Input

<View style={{ padding: 16, margin: 8 }}>

Output

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

Input

Same view

Output

<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 here
  • src/components/Skills/DocRenderer.js - renders this doc format

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.