Install

facebook/react-native

react-native Documentation

Last updated on Jan 14, 2026 (Commit: caa1fb6)

Overview

Relevant Files
  • README.md
  • CONTRIBUTING.md
  • ECOSYSTEM.md
  • docs/README.md
  • package.json

React Native is a framework for building native mobile applications using React and JavaScript. It enables developers to write code once and deploy to both iOS and Android platforms, following the principle of "learn once, write anywhere."

What is React Native?

React Native brings React's declarative UI framework to iOS and Android by providing access to native UI controls and platform APIs. Key characteristics include:

  • Declarative UI: React makes it painless to create interactive UIs with predictable, debuggable code.
  • Component-Based Architecture: Build encapsulated components that manage their own state and compose them into complex UIs.
  • Developer Velocity: See local changes in seconds with live reload capabilities without rebuilding the native app.
  • Code Reusability: Share code across iOS, Android, and other platforms like Windows and macOS.

Repository Structure

This is a monorepo containing the core React Native framework and supporting packages:

  • packages/react-native: The main public JavaScript API and core framework.
  • packages/: Additional packages including CLI tools, Babel presets, code generation, and testing utilities.
  • private/: Internal packages used for development and testing.
  • scripts/: Build, release, and testing automation scripts.

The repository uses Yarn workspaces for dependency management and supports building for Android (Gradle), iOS (Xcode), and C++ components.

Core Subsystems

React Native comprises several interconnected subsystems:

  • Runtime: JavaScript execution, feature flags, and event loop management.
  • UI Framework (Fabric): Modern rendering engine with shadow tree lifecycle, layout, and mounting.
  • Native Modules & TurboModules: Bridge between JavaScript and native platform code.
  • Developer Tools: React DevTools, LogBox, and debugging infrastructure.
  • Web APIs: DOM traversal, IntersectionObserver, MutationObserver, and timers.
  • Build System: Android Gradle, iOS Xcode, C++ compilation, and JavaScript bundling via Metro.
  • Testing: Jest, Flow, TypeScript, ESLint, and E2E testing with Fantom.

Ecosystem & Community

React Native is developed and supported by a vibrant ecosystem:

  • Partners: Companies like Meta, Microsoft, Expo, Shopify, and Wix invest significantly in React Native and maintain critical tools and libraries.
  • Core Contributors: Individual developers who consistently contribute, review changes, and manage releases.
  • Community Contributors: Maintainers of community packages in the react-native-community organization.

See ECOSYSTEM.md for detailed information about partners, their contributions, and how to become involved.

Getting Started

  • For Users: Visit reactnative.dev for official documentation, tutorials, and guides.
  • For Contributors: Read CONTRIBUTING.md and the Contributing Guide to learn about the development process, code standards, and how to submit pull requests.
  • Requirements: iOS 15.1+ and Android 7.0 (API 24)+. Development can be done on Windows, macOS, or Linux (iOS development requires macOS).

Key Resources

Architecture & Core Systems

Relevant Files
  • packages/react-native/index.js
  • packages/react-native/Libraries/ReactNative/AppRegistry.js
  • packages/react-native/Libraries/BatchedBridge/MessageQueue.js
  • packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h
  • packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h
  • packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h
  • packages/react-native/React/Fabric/RCTScheduler.h

React Native's architecture is built on a bridge-based communication model connecting JavaScript and native platforms, with the Fabric renderer providing a modern, high-performance rendering system.

Core Entry Points

AppRegistry is the JavaScript entry point for all React Native applications. It manages component registration and application lifecycle through registerComponent() and runApplication(). When an app starts, the native layer calls AppRegistry.runApplication() with the app key and initial properties, triggering the React component tree to render.

The public API (exposed via packages/react-native/index.js) uses lazy loading for all components and APIs, enabling tree-shaking and reducing bundle size. Components like View, Text, and ScrollView are loaded on-demand through getter functions.

Bridge Communication

The MessageQueue system (now deprecated in favor of TurboModules) handles asynchronous communication between JavaScript and native code. It batches calls into a queue structure with three arrays: module IDs, method IDs, and parameters. The queue flushes every 5ms or when explicitly triggered, minimizing context switches.

// Queue structure: [moduleIDs[], methodIDs[], params[], callID]
enqueueNativeCall(moduleID, methodID, params, onFail, onSucc)

Modern apps use TurboModules for synchronous, type-safe native module access with better performance.

Fabric Renderer Architecture

The Fabric renderer is React Native's modern rendering engine, replacing the legacy renderer. It consists of three main layers:

  1. Scheduler – Coordinates shadow tree updates and event flows. It manages the render cycle, batches updates, and delegates to the UIManager.

  2. UIManager – Creates and manages shadow nodes, maintains the shadow tree registry, and orchestrates surface lifecycle. It bridges JavaScript render updates to native mounting operations.

  3. ShadowNode – Immutable tree representation of the component hierarchy. Each node holds props, children, state, and layout information. Nodes are sealed after creation to ensure immutability and enable safe concurrent updates.

Loading diagram...

Surface Lifecycle

A Surface represents a single React root (e.g., a screen or modal). When UIManager.startSurface() is called:

  1. A new ShadowTree is created and registered
  2. The Scheduler receives the module name and initial props
  3. AppRegistryBinding.startSurface() executes in the JavaScript runtime
  4. React renders the component tree, producing shadow nodes
  5. Layout calculations occur via Yoga
  6. The mounting coordinator generates mutations
  7. Native views are created and updated on the UI thread

Component Descriptors

ComponentDescriptor factories create and clone shadow nodes for each component type. They handle props parsing, state management, and component-specific behavior. The descriptor registry maps component names to their factories, enabling dynamic component creation.

Event System

Events flow from native to JavaScript through the EventDispatcher. Raw events are processed by EventQueueProcessor, which batches them and executes listeners. This decouples event handling from the render cycle, improving performance.

Key Design Principles

  • Immutability: Shadow nodes are sealed after creation, enabling safe concurrent updates
  • Batching: Updates and events are batched to minimize bridge crossings
  • Asynchrony: Most operations are asynchronous, with explicit synchronous paths for animations
  • Delegation: Scheduler delegates to UIManager, which delegates to platform-specific mounting managers

TurboModules & Native Modules

Relevant Files
  • packages/react-native/Libraries/TurboModule/TurboModuleRegistry.js
  • packages/react-native/Libraries/TurboModule/RCTExport.js
  • packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h
  • packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp
  • packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h
  • packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManager.kt

TurboModules are React Native's modern native module system, designed to provide faster and more type-safe communication between JavaScript and native code. They replace the legacy bridge-based module system with a JSI (JavaScript Interface) based approach that enables synchronous method calls and better performance.

Architecture Overview

Loading diagram...

Key Components

TurboModuleRegistry (JavaScript entry point) provides two methods to access modules:

  • get(name) - Returns a module or null if not found
  • getEnforcing(name) - Throws an error if the module doesn't exist

The registry first checks global.__turboModuleProxy for TurboModules, then falls back to legacy NativeModules for backward compatibility.

TurboModule Base Class (C++) is a JSI HostObject that:

  • Manages method metadata and property caching
  • Handles method invocation through a methodMap
  • Supports event emission via emitDeviceEvent()
  • Provides automatic property caching on the JS representation

Platform-Specific Managers handle module instantiation:

  • iOS (RCTTurboModuleManager) - Creates ObjCTurboModule instances wrapping Objective-C modules
  • Android (TurboModuleManager.kt) - Manages Java module creation with thread-safe caching via ModuleHolder

Module Lifecycle

  1. Registration - Modules are registered through platform-specific delegates
  2. Lazy Loading - Modules are created on first access (unless eager-initialized)
  3. Caching - Created modules are cached to avoid recreation
  4. Cleanup - Modules are invalidated when the runtime shuts down

Type Safety & Codegen

TurboModules use Flow/TypeScript interfaces that extend TurboModule. The codegen system generates native implementations from these specs, ensuring type safety across the bridge. This eliminates runtime type mismatches common in legacy modules.

Backward Compatibility

TurboModules coexist with legacy modules. The system checks for TurboModules first via __turboModuleProxy, then falls back to nativeModuleProxy for legacy modules. This allows gradual migration without breaking existing code.

Performance Benefits

  • Synchronous calls - Direct JSI access eliminates bridge serialization overhead
  • Type safety - Codegen prevents runtime errors
  • Lazy loading - Modules load only when needed
  • Caching - Avoids repeated instantiation

UI Components & Views

Relevant Files
  • packages/react-native/Libraries/Components/View/View.js
  • packages/react-native/Libraries/Components/ScrollView/ScrollView.js
  • packages/react-native/Libraries/Lists/FlatList.js
  • packages/react-native/Libraries/Image/Image.ios.js
  • packages/react-native/Libraries/Text/Text.js

React Native provides a comprehensive set of UI components that map directly to native platform views. These components form the foundation of all React Native applications, enabling developers to build cross-platform interfaces using familiar React patterns.

Core Components

View is the most fundamental building block. It's a container component that supports flexbox layout, styling, touch handling, and accessibility controls. Every UI element in React Native ultimately renders as a View or a specialized subclass. View maps directly to UIView on iOS and android.view.ViewGroup on Android.

Text is the primary component for displaying text content. It supports font scaling, ellipsization, and press events. Text components can be nested, and they automatically inherit text styling from parent Text components through the TextAncestorContext. This context prevents Views from being rendered inside Text elements, maintaining proper text rendering semantics.

ScrollView wraps platform ScrollView implementations while integrating with React Native's responder system. It requires bounded height to function properly and supports both vertical and horizontal scrolling. Key features include momentum scrolling, scroll event callbacks, and sticky headers. ScrollView uses ScrollViewContext to communicate scroll state to child components.

List Components

FlatList is the recommended component for rendering large lists efficiently. It uses virtualization to render only visible items, dramatically improving performance for long lists. FlatList accepts a data array and renderItem function, with optional support for headers, footers, and item separators. The getItemLayout prop enables further optimization for fixed-height items.

VirtualizedList is the underlying virtualization engine powering FlatList and SectionList. It manages viewport calculations, item rendering, and scroll position tracking. Developers typically use FlatList instead of VirtualizedList directly, but understanding VirtualizedList is essential for custom list implementations.

Image Component

Image displays images from various sources including network URLs, local files, and bundled assets. It supports multiple image formats and provides methods like getSize() and prefetch() for image management. Image uses ImageViewNativeComponent to render platform-specific image views with support for resize modes, caching, and analytics tracking.

Native Component Architecture

Loading diagram...

All UI components ultimately render through native components created via codegenNativeComponent() or requireNativeComponent(). These functions bridge JavaScript props to native view managers. The bridge serializes prop changes and event data, enabling seamless JS-to-native communication.

Styling and Layout

React Native components use a subset of CSS for styling, with flexbox as the default layout engine. Styles are defined as JavaScript objects and processed through StyleSheet.create() for optimization. The ViewPropTypes module defines all valid props for View components, including layout, style, accessibility, and event handler props.

Accessibility

All core components support comprehensive accessibility features including accessibilityLabel, accessibilityRole, accessibilityState, and ARIA attributes. These props map to platform-specific accessibility APIs, ensuring applications are usable by assistive technologies on both iOS and Android.

Styling, Layout & Yoga

Relevant Files
  • packages/react-native/Libraries/StyleSheet/StyleSheet.js
  • packages/react-native/Libraries/StyleSheet/StyleSheetExports.js
  • packages/react-native/Libraries/StyleSheet/processColor.js
  • packages/react-native/Libraries/StyleSheet/processTransform.js
  • packages/react-native/ReactCommon/yoga/yoga/Yoga.h
  • packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp

React Native's styling system bridges JavaScript style objects with native platform rendering through a multi-stage pipeline: style creation, processing, layout calculation, and native application.

StyleSheet API

The StyleSheet.create() function is an identity function that freezes style objects in development for immutability and enables static type checking. It accepts a style object and returns it as a read-only type. Key utilities include:

  • StyleSheet.flatten() - Recursively merges arrays of style objects into a single object, with later styles overriding earlier ones
  • StyleSheet.compose() - Combines two styles where the second overrides the first, optimizing for reference equality
  • StyleSheet.hairlineWidth - Platform-specific thin line width (typically 1 pixel or less)
  • StyleSheet.absoluteFillObject - Convenience object for absolute positioning with zero insets

Style Processing Pipeline

Styles flow through a processing system before reaching native code:

  1. Color Processing (processColor.js) - Converts color strings/objects to platform-specific formats. On Android, converts RGBA to ARGB and handles signed 32-bit integers. On iOS, preserves platform color objects.

  2. Transform Processing (processTransform.js) - Parses CSS-like transform strings or arrays into a unified format. Supports translate, scale, rotate, skew, and perspective operations.

  3. Other Processors - Specialized handlers for filters, box shadows, background images, and aspect ratios. Each processor validates input and converts to native-compatible formats.

Yoga Layout Engine

Yoga is a cross-platform flexbox implementation (C++) that calculates layout for all React Native views. Key concepts:

  • Yoga Nodes - Each view has an associated YGNode that stores style properties and computed layout metrics
  • Layout Calculation - YGNodeCalculateLayout() computes positions and sizes based on flexbox rules, constraints, and style properties
  • Dirty Flagging - Nodes marked dirty trigger recalculation; unchanged nodes skip computation for performance
  • Errata System - Handles platform-specific layout quirks and CSS spec deviations

Integration with Fabric Renderer

In the modern Fabric renderer, YogaLayoutableShadowNode wraps Yoga nodes:

  • Converts JavaScript style props to Yoga style objects via updateYogaProps()
  • Manages Yoga tree hierarchy matching the React component tree
  • Calls layoutTree() to compute layout with point scale factors and RTL support
  • Emits layout events after calculation completes

The layout pipeline ensures styles defined in JavaScript are efficiently processed, validated, and applied to native views with proper platform-specific handling.

Animations & Interactions

Relevant Files
  • packages/react-native/Libraries/Animated/Animated.js
  • packages/react-native/Libraries/Animated/AnimatedImplementation.js
  • packages/react-native/Libraries/Animated/nodes/AnimatedValue.js
  • packages/react-native/Libraries/Interaction/InteractionManager.js
  • packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.h

Core Concepts

React Native's animation system is built on declarative value graphs where nodes represent values or transform operations, and connections describe how changes propagate. The Animated library focuses on smooth, performant animations by supporting both JavaScript and native drivers.

Key principles:

  • Animations are driven by Animated.Value instances that can be updated by animation engines or directly via setValue()
  • Values can be connected to view properties, creating reactive updates
  • The native driver offloads animation execution to the platform thread for 60 FPS performance
  • Easing functions control motion curves for natural-feeling animations

Animation Types

React Native provides three primary animation drivers:

Timing Animation (Animated.timing()) - Linear or eased progression from one value to another over a specified duration. Ideal for standard UI transitions.

Spring Animation (Animated.spring()) - Physics-based animation with configurable tension and friction. Creates natural bouncing effects and is commonly used for interactive gestures.

Decay Animation (Animated.decay()) - Simulates momentum-based deceleration. Perfect for scroll-like interactions where velocity gradually decreases.

All animations return a CompositeAnimation object with start(), stop(), and reset() methods for lifecycle control.

Composition & Sequencing

Complex animations are built by composing simpler ones:

// Run animations sequentially
Animated.sequence([
  Animated.timing(value1, {toValue: 100, duration: 500}),
  Animated.timing(value2, {toValue: 200, duration: 500}),
]).start();

// Run animations in parallel
Animated.parallel([
  Animated.timing(value1, {toValue: 100, duration: 500}),
  Animated.timing(value2, {toValue: 200, duration: 500}),
]).start();

// Stagger animations with delays
Animated.stagger(100, [anim1, anim2, anim3]).start();

// Loop animations indefinitely
Animated.loop(animation).start();

Value Transformations

Animated values can be transformed using mathematical operations:

const value = new Animated.Value(0);
const doubled = Animated.multiply(value, 2);
const interpolated = value.interpolate({
  inputRange: [0, 100],
  outputRange: [0, 360],
});

Supported operations: add(), subtract(), multiply(), divide(), modulo(), diffClamp(), and interpolate() for mapping ranges.

Native Driver Optimization

Setting useNativeDriver: true executes animations on the native thread, bypassing the JavaScript bridge:

Animated.timing(value, {
  toValue: 100,
  duration: 500,
  useNativeDriver: true,
}).start();

Constraints: Only certain properties support native driver (transforms, opacity). Complex operations like interpolate() with non-linear ranges may require JavaScript execution.

InteractionManager

InteractionManager schedules long-running tasks after animations complete, preventing jank:

InteractionManager.runAfterInteractions(() => {
  // Heavy computation runs after animations finish
  expensiveDataFetch();
});

Create interaction handles to register custom animations:

const handle = InteractionManager.createInteractionHandle();
// Run animation...
InteractionManager.clearInteractionHandle(handle);

Note: InteractionManager is deprecated in favor of modern scheduling APIs.

Easing Functions

The Easing module provides predefined curves for natural motion:

  • Standard: linear, quad, cubic, poly
  • Predefined: ease, back, bounce, elastic
  • Modifiers: in(), out(), inOut() for direction control
  • Custom: bezier() for cubic Bézier curves
Animated.timing(value, {
  toValue: 100,
  duration: 500,
  easing: Easing.bezier(0.25, 0.1, 0.25, 1),
}).start();

Architecture Overview

Loading diagram...

The animation system maintains a graph of nodes where each node can listen for value changes and propagate updates to dependent nodes. The native animated module batches operations for efficiency.

Networking, Storage & APIs

Relevant Files
  • packages/react-native/Libraries/Network/fetch.js
  • packages/react-native/Libraries/Network/XMLHttpRequest.js
  • packages/react-native/Libraries/Network/RCTNetworking.ios.js
  • packages/react-native/Libraries/Network/RCTNetworking.android.js
  • packages/react-native/Libraries/Network/FormData.js
  • packages/react-native/Libraries/Blob/Blob.js
  • packages/react-native/Libraries/Blob/BlobManager.js
  • packages/react-native/Libraries/WebSocket/WebSocket.js

React Native provides a comprehensive networking and storage layer that bridges JavaScript APIs with native platform capabilities. This section covers HTTP requests, WebSockets, and binary data handling.

HTTP Requests & Fetch API

React Native implements the standard Fetch API through the whatwg-fetch polyfill, exposing fetch, Headers, Request, and Response globally. The underlying implementation uses platform-specific native modules:

  • iOS: RCTNetworking.ios.js delegates to NativeNetworkingIOS
  • Android: RCTNetworking.android.js delegates to NativeNetworkingAndroid

Both platforms support request cancellation, custom headers, timeouts, and incremental response updates. The convertRequestBody utility normalizes various request body types (strings, Blobs, FormData, ArrayBuffers) into platform-compatible formats.

XMLHttpRequest Implementation

XMLHttpRequest.js provides a W3C-compliant XHR implementation with full event support. Key features include:

  • Response types: text, json, blob, arraybuffer, and empty string (default)
  • Event system: Inherits from EventTarget with load, loadstart, progress, timeout, and error events
  • State machine: Follows standard XHR states (UNSENT, OPENED, HEADERS_RECEIVED, LOADING, DONE)
  • Blob integration: Automatically registers with BlobManager for binary response handling

FormData & Multipart Requests

FormData.js enables multipart form submissions with mixed data types. It supports appending strings and file objects with metadata:

const form = new FormData();
form.append('field', 'value');
form.append('file', {uri: 'file://path', type: 'image/jpeg', name: 'photo.jpg'});
xhr.send(form);

On Android, headers are converted to arrays for efficient native consumption.

Binary Data & Blobs

The Blob class provides a W3C-compatible interface for opaque binary data. Key aspects:

  • Lifecycle management: Blobs must be explicitly closed to free native resources via blob.close()
  • UUID-based tracking: Each Blob gets a unique identifier for native resource management
  • Slicing: Supports the slice() method to create sub-blobs
  • Integration: Works seamlessly with fetch, XHR, and WebSocket APIs

BlobManager handles creation from parts, registry tracking, and networking integration.

WebSocket Support

WebSocket.js implements the standard WebSocket API with native bridging:

  • Binary modes: Supports both blob and arraybuffer binary types
  • State constants: CONNECTING, OPEN, CLOSING, CLOSED
  • Event handling: open, message, close, and error events via EventTarget
  • Blob support: Automatically manages Blob resources when binaryType is set to 'blob'
const ws = new WebSocket('ws://example.com');
ws.binaryType = 'blob';
ws.onmessage = (event) => {
  const blob = event.data;
  // Use blob...
  blob.close();
};

Architecture Overview

Loading diagram...

The networking stack prioritizes standards compliance while leveraging native platform capabilities for performance and reliability.

Code Generation & Tooling

Relevant Files
  • packages/react-native-codegen – Core code generation engine
  • packages/babel-plugin-codegen – Babel plugin for compile-time code generation
  • packages/react-native-babel-preset – Babel preset integrating codegen
  • packages/react-native/scripts/codegen – CLI executors and artifact generation

React Native uses a sophisticated code generation system to automatically create native bindings and type-safe interfaces for components and modules. This system bridges JavaScript and native code (iOS, Android, C++) by parsing type annotations and generating platform-specific implementations.

Architecture Overview

Loading diagram...

Core Components

@react-native/codegen is the main code generation engine. It:

  • Parses Flow and TypeScript type annotations from component and module specs
  • Validates schemas against a strict specification
  • Generates platform-specific code for iOS (Objective-C++), Android (Java/JNI), and C++
  • Produces type-safe native bindings and descriptors

@react-native/babel-plugin-codegen runs during the Babel transpilation phase. It:

  • Detects codegenNativeComponent and codegenNativeCommands declarations
  • Generates ViewConfig objects at compile time
  • Replaces component exports with generated configuration
  • Enables static analysis of component props and events

@react-native/babel-preset integrates the Babel plugin into the standard React Native build pipeline, automatically enabling codegen for files matching *NativeComponent.(js|ts) patterns.

Generation Pipeline

The codegen system supports two main workflows:

Library Generation processes individual component or module specs:

  1. Parse the source file (Flow or TypeScript)
  2. Extract type information into a schema
  3. Generate platform-specific code for selected generators
  4. Write files to output directories organized by platform

Artifact Generation (used by apps) orchestrates the full build:

  1. Discover all libraries with codegenConfig in package.json
  2. Extract schemas from each library
  3. Generate native code for the target platform (iOS/Android)
  4. Create platform-specific providers and dependency injection files
  5. Clean up empty directories

Generator Types

The system provides specialized generators for different artifacts:

  • Components: Descriptors, Props, State, Events, Shadow Nodes (iOS/Android)
  • Modules: JNI bindings (Android), Objective-C++ wrappers (iOS), C++ headers
  • Providers: Dependency injection, URL handlers, module registries (iOS only)
  • Tests: Unit test scaffolding for generated code

Each generator produces a Map<fileName, fileContent> that gets written to platform-specific output directories.

Schema Validation

All generated code is validated against CodegenSchema, which enforces:

  • Type safety for props, state, and method parameters
  • Consistent naming conventions
  • Platform-specific constraints (e.g., nullable types on iOS)
  • Proper event and command definitions

Invalid schemas fail fast with detailed error messages, preventing invalid native code generation.

Integration Points

  • Metro bundler: Babel preset automatically applies the codegen plugin
  • CocoaPods (iOS): Ruby scripts invoke codegen during pod install
  • Gradle (Android): Kotlin tasks build and execute codegen CLI
  • Package.json: codegenConfig field specifies which libraries to generate

Platform-Specific Implementation

Relevant Files
  • packages/react-native/ReactCommon – Cross-platform C++ core
  • packages/react-native/ReactApple – iOS/macOS implementations
  • packages/react-native/ReactAndroid – Android implementations
  • packages/react-native/ReactCxxPlatform – Platform-specific C++ modules
  • packages/react-native/React – Objective-C bridge layer
  • packages/react-native/Libraries – JavaScript APIs with platform selection

React Native achieves cross-platform compatibility through a layered architecture that separates shared logic from platform-specific implementations. The codebase is organized into distinct directories, each serving a specific purpose in the platform abstraction strategy.

Architecture Overview

The platform-specific implementation follows a three-tier model:

  1. ReactCommon – Platform-agnostic C++ core containing shared business logic, rendering engine, and utilities
  2. Platform-Specific Layers – ReactApple (iOS/macOS), ReactAndroid (Android), and ReactCxxPlatform (C++ platform modules)
  3. Language Bridges – Objective-C for Apple, Java/JNI for Android, and JavaScript for application code
Loading diagram...

Directory Structure Pattern

Platform-specific code is organized using a consistent directory pattern:

component/
├── *.cpp, *.h          # Shared cross-platform code
├── platform/
│   ├── ios/            # iOS-specific implementations
│   ├── android/        # Android-specific implementations
│   └── cxx/            # C++ fallback implementations
└── tests/              # Shared tests

Examples include react/renderer/components/view/platform/, react/runtime/platform/, and react/nativemodule/core/platform/.

Build-Time Platform Selection

CMake uses the react_native_android_selector() function to conditionally include platform-specific source files:

react_native_android_selector(platform_SRC
    platform/android/react/renderer/graphics/*.cpp
    platform/cxx/react/renderer/graphics/*.cpp)

This selects Android implementations when building for Android, and C++ fallbacks otherwise. iOS uses Podspec files with explicit source file patterns like platform/ios/**/*.{m,mm,cpp,h}.

JavaScript Platform Detection

The Platform module provides runtime platform detection:

import {Platform} from 'react-native';

Platform.select({
  ios: () => <IOSComponent />,
  android: () => <AndroidComponent />,
  default: () => <DefaultComponent />,
});

Platform constants (version, OS, device info) are exposed through native modules like RCTPlatform (iOS) and PlatformConstantsModule (Android).

Key Abstractions

Shared Interfaces – Components define abstract interfaces in ReactCommon that platform layers implement. For example, ImageManager has iOS implementations in platform/ios/ and Android implementations in platform/android/.

Conditional Compilation – C++ code uses preprocessor directives and CMake conditionals to exclude platform-specific code at compile time, reducing binary size.

Dependency Injection – Platform-specific implementations are registered via ContextContainer, allowing ReactCommon to access platform services without direct dependencies.

Build System Integration

  • iOS/macOS: CocoaPods with Podspec files specify platform-specific source files and frameworks
  • Android: Gradle with CMake integration; platform selection happens during JNI compilation
  • Swift Package Manager: Header mappings route platform-specific includes to correct locations

Testing, Debugging & Development Tools

Relevant Files
  • packages/rn-tester - Test application and testing infrastructure
  • packages/react-native/Libraries/LogBox - In-app error and warning display
  • packages/react-native/Libraries/Debugging - Debugging overlay components
  • private/react-native-fantom - Integration testing and benchmarking framework
  • jest.config.js - Jest test configuration
  • packages/react-native/jest-preset.js - Jest preset for React Native

React Native provides a comprehensive testing and debugging ecosystem spanning unit tests, integration tests, and in-app debugging tools.

Jest Unit Testing

Jest is the primary unit testing framework. The root jest.config.js configures test discovery with the /__tests__/.*-test(\\.fb)?\\.js$ pattern. Tests use Babel transformation and include setup files that configure the test environment with polyfills and mocks.

Key features:

  • Snapshot testing - Compare rendered output against stored snapshots
  • Module mocking - Mock native modules and dependencies
  • Coverage collection - Track code coverage across the Libraries directory
  • Fake timers - Control async behavior in tests

Run tests with yarn test from the repository root.

Fantom: Integration Testing Framework

Fantom is the modern integration testing tool for React Native, enabling headless testing of JavaScript code with real layout calculations and native integration. Unlike Jest, Fantom tests can inspect actual layout metrics and test interactions between JavaScript and native code without simulators.

Create tests with the -itest.js suffix:

import * as Fantom from '@react-native/fantom';

describe('Layout Test', () => {
  it('calculates dimensions correctly', () => {
    const root = Fantom.createRoot({viewportWidth: 200, viewportHeight: 600});
    
    Fantom.runTask(() => {
      root.render(<View style={{width: '50%', height: '10%'}} />);
    });
    
    const rect = viewElement.getBoundingClientRect();
    expect(rect.width).toBe(100);
  });
});

Run with: yarn fantom <regexForTestFiles>

Debug JavaScript with FANTOM_DEBUG_JS=1 or C++ with FANTOM_DEBUG_CPP=1.

LogBox: In-App Error Display

LogBox intercepts console warnings and errors, displaying them in a dismissible overlay during development. It provides stack traces, source maps, and filtering capabilities.

Key methods:

  • LogBox.install() - Enable LogBox (automatic in dev mode)
  • LogBox.ignoreLogs(patterns) - Suppress specific warnings
  • LogBox.clearAllLogs() - Clear all displayed logs

LogBox is disabled during testing (Platform.isTesting), allowing tests to verify error handling without UI interference.

RCTTest: Native Testing Infrastructure

The RCTTest framework (packages/rn-tester/RCTTest) provides snapshot testing and integration testing for native code. RCTTestRunner manages test execution, error collection, and snapshot verification.

Features:

  • Snapshot comparison with reference images
  • Error expectation matching via regex or custom blocks
  • Root view configuration and manipulation
  • Timeout handling with 30-second limits

Testing Utilities

ReactNativeTestTools.js exports helpers for component testing:

  • byTestID(id) - Find components by testID prop
  • byTextMatching(regex) - Find components by text content
  • byClickable() - Find interactive components
  • tap(instance) - Simulate touch events
  • enter(instance, text) - Simulate text input
  • expectNoConsoleWarn() / expectNoConsoleError() - Assert clean console output

Test Organization

Tests follow a consistent structure:

  • Unit tests: __tests__/*-test.js (Jest)
  • Integration tests: __tests__/*-itest.js (Fantom)
  • Native tests: RNTesterUnitTests/ and RNTesterIntegrationTests/ (Objective-C/Swift)
  • Android tests: ReactAndroid/src/test/ (Java/Kotlin)

The RNTester app (packages/rn-tester) serves as both a showcase and testing ground for React Native components and APIs.