React Native Guide: Mobile App Development with JavaScript
React Native extends React’s component model to mobile platforms. Instead of rendering to DOM elements, React Native renders to native platform components — UIView on iOS and View on Android. This means a React Native app has the look and feel of a native app while being written in JavaScript. As the React Native documentation states: “Learn once, write anywhere.”
Core Components and APIs
React Native provides a set of core components that map to native UI elements:
- View — The fundamental layout container (maps to
UIView/View) - Text — For displaying text (maps to
UILabel/TextView) - ScrollView — A scrollable container
- FlatList — A performant scrolling list for large data sets
- Pressable — A wrapper for handling touch interactions
- TextInput — For text input
- Image — For displaying images
import { View, Text, FlatList } from 'react-native';
function PostList({ posts }) {
return (
<FlatList
data={posts}
renderItem={({ item }) => <View><Text>{item.title}</Text></View>}
keyExtractor={item => item.id}
/>
);
---Platform-Specific Code
React Native provides mechanisms to handle platform differences. Files with .ios.js and .android.js extensions are automatically selected based on the platform. The Platform API allows conditional logic:
import { Platform } from 'react-native';
const styles = Platform.select({
ios: { shadowColor: '#000' },
android: { elevation: 3 },
---);Navigation
Navigation in React Native is handled by React Navigation, the community-maintained navigation library recommended by the React Native documentation. It provides a stack navigator, tab navigator, and drawer navigator:
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={Profile} />
</Stack.Navigator>
</NavigationContainer>
);
---React Navigation v7 (the latest version) supports type-safe navigation with TypeScript, native stack transitions for performance, and deep linking for universal links and custom URL schemes.
Styling in React Native
React Native uses a JavaScript-based styling system similar to CSS but with key differences. Styles are defined as JavaScript objects with camelCase properties:
const styles = StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: 16,
},
title: {
fontSize: 18,
fontWeight: 'bold',
},
---);StyleSheet.create validates styles and optimizes them for native rendering. React Native uses Flexbox for layout (defaulting to flexDirection: 'column', unlike CSS’s default row). All dimensions are unitless — React Native works in density-independent pixels.
Expo vs React Native CLI
Expo is a managed framework built on top of React Native. It provides a set of pre-configured tools, SDK modules, and build services that significantly simplify development:
- Expo Go: Test your app on a physical device without Xcode or Android Studio
- EAS Build: Cloud-based builds for iOS and Android
- Expo SDK: Pre-built native modules for camera, location, notifications, and more
The React Native documentation now recommends Expo for new projects. Expo SDK 52+ supports all major React Native features, including the New Architecture (Fabric renderer and TurboModules). The React Native team and Expo team have been collaborating closely since 2023.
Choose React Native CLI when you need custom native modules that Expo does not support, or when you need direct control over the native build process.
Native Modules and the New Architecture
React Native’s New Architecture, finalized in React Native 0.76, includes:
- Fabric: The new rendering system that replaces the old bridge with a synchronous, native-driven UI manager
- TurboModules: Efficient module loading with lazy initialization and type-safe interfaces
- JSI (JavaScript Interface): Direct C++ communication between JavaScript and native code, replacing the async bridge
The New Architecture improves startup time, reduces memory usage, and enables synchronous native method calls. The React Native documentation provides migration guides for existing projects.
Creating Native Modules
When you need platform-specific functionality not available in the standard library:
// Android
@ReactMethod
fun showToast(message: String) {
Toast.makeText(currentActivity, message, Toast.LENGTH_SHORT).show()
---For most projects, Expo’s module system or community libraries cover these needs without writing native code.
State Management in React Native
React Native applications face unique state management challenges related to mobile lifecycle events — app backgrounding, network connectivity changes, and memory constraints.
For global state, Zustand and Jotai work identically to their web counterparts. The key difference is that mobile apps often need to persist more state (user preferences, draft content, offline data) using AsyncStorage or MMKV (a fast key-value storage library).
import { MMKV } from 'react-native-mmkv';
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
const storage = new MMKV();
const useStore = create(persist(
(set) => ({ theme: 'light', setTheme: (t) => set({ theme: t }) }),
{ name: 'settings', storage: createJSONStorage(() => storage) }
));Offline-First Architecture
Mobile apps frequently operate with unreliable network connections. Offline-first patterns store data locally and sync with the server when connectivity returns:
- Use
react-native-quick-sqliteor WatermelonDB for local databases - Queue mutations with
@tanstack/react-query’sonlineManager - Display stale data while fetching updates in the background
The React Native documentation on networking covers the NetInfo API for detecting connectivity changes, and libraries like Redux Offline provide comprehensive offline queues.
Animations
Animations in React Native are handled by the Animated API or the newer react-native-reanimated library:
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
function AnimatedBox() {
const offset = useSharedValue(0);
const animatedStyles = useAnimatedStyle(() => ({
transform: [{ translateX: withSpring(offset.value) }],
}));
return (
<Animated.View style={[styles.box, animatedStyles]} />
);
---Reanimated runs animations on the UI thread instead of the JavaScript thread, ensuring smooth animations even during heavy JavaScript work. The React Native documentation recommends Reanimated for complex animations and transitions.
Performance Optimization
React Native performance optimization focuses on the JavaScript thread, the native thread, and the bridge (now replaced by JSI).
Linking and Deep Linking
React Native supports deep linking to open specific screens from push notifications, URLs, or external apps. React Navigation’s linking configuration maps URL patterns to navigation state:
const linking = {
prefixes: ['myapp://', 'https://myapp.com'],
config: {
screens: {
Home: '',
Profile: 'user/:id',
Settings: 'settings',
},
},
---;
<NavigationContainer linking={linking}>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={Profile} />
</Stack.Navigator>
</NavigationContainer>Universal Links (iOS) and App Links (Android) allow your app to handle HTTP URLs, providing seamless transitions from web to app. The React Navigation deep linking guide covers configuration for both platforms, including handling authentication flows and error states during navigation.
Debugging React Native
React Native provides multiple debugging tools:
- Flipper: Meta’s desktop debugging tool for React Native, providing network inspection, layout inspector, crash reporter, and database viewer
- React DevTools: Works with React Native for component tree inspection and profiling
- React Native Debugger: Standalone debugger combining Redux DevTools and React DevTools
The React Native debugger’s “Inspector” mode overlays component boundaries and dimensions on the device, making layout debugging visual and intuitive. The Flipper network plugin is invaluable for debugging API calls and authentication flows.
FlatList vs ScrollView
FlatList uses windowing — it only renders items that are visible on screen plus a small overscan buffer. ScrollView renders all children at once. For lists with more than 20 items, always use FlatList or SectionList.
InteractionManager
Use InteractionManager.runAfterInteractions to defer expensive work until after animations and transitions complete:
InteractionManager.runAfterInteractions(() => {
loadHeavyData();
---);Hermes
Hermes is an open-source JavaScript engine optimized for React Native. It improves startup time, reduces memory usage, and shrinks app size. It is the default engine in React Native 0.70+ and enables ahead-of-time (AOT) compilation of JavaScript to bytecode.
FAQ
Can I use React Native for web and desktop?
React Native’s architecture has been adapted for other platforms: React Native for Windows + macOS, and React Native for Web (which maps components to DOM elements). However, these are separate projects with their own considerations.
Should I use Expo or React Native CLI?
Use Expo for new projects. Expo’s managed workflow handles 95% of use cases and significantly reduces build complexity. Only use bare React Native CLI when you need custom native modules that Expo does not support.
How does React Native compare to Flutter?
React Native uses native components, giving it a more platform-native look and feel. Flutter paints its own widgets with Skia, giving more consistent cross-platform appearance. React Native has a larger ecosystem and hiring market; Flutter offers slightly better animation performance.
Do I need to know iOS and Android development?
Not for most React Native development. Native module development requires Swift/Objective-C or Kotlin/Java, but the vast majority of apps can be built with JavaScript and React Native’s core libraries.
Conclusion
React Native enables cross-platform mobile development with a single JavaScript codebase, sharing up to 90% of code between iOS and Android. The New Architecture (Fabric, TurboModules, JSI) brings performance parity with native development. The official React Native documentation at reactnative.dev and the Expo documentation at docs.expo.dev are the best starting points. For understanding the shared concepts between React and React Native, see React Components, and for testing your mobile app, explore React Testing Library.
For a comprehensive overview, read our article on Next Js Guide.
For a comprehensive overview, read our article on React Authentication.