Overview
Relevant Files
README.mdCONTRIBUTING.mdECOSYSTEM.mddocs/README.mdpackage.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-communityorganization.
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.mdand 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
- Documentation: reactnative.dev
- Contributing: Contributing Guide
- Roadmap: GitHub Wiki Roadmap
- Discussions: react-native-community/discussions-and-proposals
- Good First Issues: GitHub Issues
Architecture & Core Systems
Relevant Files
packages/react-native/index.jspackages/react-native/Libraries/ReactNative/AppRegistry.jspackages/react-native/Libraries/BatchedBridge/MessageQueue.jspackages/react-native/ReactCommon/react/renderer/core/ShadowNode.hpackages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.hpackages/react-native/ReactCommon/react/renderer/uimanager/UIManager.hpackages/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:
-
Scheduler – Coordinates shadow tree updates and event flows. It manages the render cycle, batches updates, and delegates to the UIManager.
-
UIManager – Creates and manages shadow nodes, maintains the shadow tree registry, and orchestrates surface lifecycle. It bridges JavaScript render updates to native mounting operations.
-
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:
- A new
ShadowTreeis created and registered - The Scheduler receives the module name and initial props
AppRegistryBinding.startSurface()executes in the JavaScript runtime- React renders the component tree, producing shadow nodes
- Layout calculations occur via Yoga
- The mounting coordinator generates mutations
- 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.jspackages/react-native/Libraries/TurboModule/RCTExport.jspackages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.hpackages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpppackages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.hpackages/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 foundgetEnforcing(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) - CreatesObjCTurboModuleinstances wrapping Objective-C modules - Android (
TurboModuleManager.kt) - Manages Java module creation with thread-safe caching viaModuleHolder
Module Lifecycle
- Registration - Modules are registered through platform-specific delegates
- Lazy Loading - Modules are created on first access (unless eager-initialized)
- Caching - Created modules are cached to avoid recreation
- 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.jspackages/react-native/Libraries/Components/ScrollView/ScrollView.jspackages/react-native/Libraries/Lists/FlatList.jspackages/react-native/Libraries/Image/Image.ios.jspackages/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.jspackages/react-native/Libraries/StyleSheet/StyleSheetExports.jspackages/react-native/Libraries/StyleSheet/processColor.jspackages/react-native/Libraries/StyleSheet/processTransform.jspackages/react-native/ReactCommon/yoga/yoga/Yoga.hpackages/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 onesStyleSheet.compose()- Combines two styles where the second overrides the first, optimizing for reference equalityStyleSheet.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:
-
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. -
Transform Processing (
processTransform.js) - Parses CSS-like transform strings or arrays into a unified format. Supportstranslate,scale,rotate,skew, andperspectiveoperations. -
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
YGNodethat 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.jspackages/react-native/Libraries/Animated/AnimatedImplementation.jspackages/react-native/Libraries/Animated/nodes/AnimatedValue.jspackages/react-native/Libraries/Interaction/InteractionManager.jspackages/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.Valueinstances that can be updated by animation engines or directly viasetValue() - 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.jspackages/react-native/Libraries/Network/XMLHttpRequest.jspackages/react-native/Libraries/Network/RCTNetworking.ios.jspackages/react-native/Libraries/Network/RCTNetworking.android.jspackages/react-native/Libraries/Network/FormData.jspackages/react-native/Libraries/Blob/Blob.jspackages/react-native/Libraries/Blob/BlobManager.jspackages/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.jsdelegates toNativeNetworkingIOS - Android:
RCTNetworking.android.jsdelegates toNativeNetworkingAndroid
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
EventTargetwithload,loadstart,progress,timeout, anderrorevents - State machine: Follows standard XHR states (UNSENT, OPENED, HEADERS_RECEIVED, LOADING, DONE)
- Blob integration: Automatically registers with
BlobManagerfor 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
blobandarraybufferbinary types - State constants: CONNECTING, OPEN, CLOSING, CLOSED
- Event handling:
open,message,close, anderrorevents viaEventTarget - Blob support: Automatically manages Blob resources when
binaryTypeis 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 enginepackages/babel-plugin-codegen– Babel plugin for compile-time code generationpackages/react-native-babel-preset– Babel preset integrating codegenpackages/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
codegenNativeComponentandcodegenNativeCommandsdeclarations - 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:
- Parse the source file (Flow or TypeScript)
- Extract type information into a schema
- Generate platform-specific code for selected generators
- Write files to output directories organized by platform
Artifact Generation (used by apps) orchestrates the full build:
- Discover all libraries with
codegenConfigin package.json - Extract schemas from each library
- Generate native code for the target platform (iOS/Android)
- Create platform-specific providers and dependency injection files
- 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:
codegenConfigfield specifies which libraries to generate
Platform-Specific Implementation
Relevant Files
packages/react-native/ReactCommon– Cross-platform C++ corepackages/react-native/ReactApple– iOS/macOS implementationspackages/react-native/ReactAndroid– Android implementationspackages/react-native/ReactCxxPlatform– Platform-specific C++ modulespackages/react-native/React– Objective-C bridge layerpackages/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:
- ReactCommon – Platform-agnostic C++ core containing shared business logic, rendering engine, and utilities
- Platform-Specific Layers – ReactApple (iOS/macOS), ReactAndroid (Android), and ReactCxxPlatform (C++ platform modules)
- 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 infrastructurepackages/react-native/Libraries/LogBox- In-app error and warning displaypackages/react-native/Libraries/Debugging- Debugging overlay componentsprivate/react-native-fantom- Integration testing and benchmarking frameworkjest.config.js- Jest test configurationpackages/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 warningsLogBox.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 propbyTextMatching(regex)- Find components by text contentbyClickable()- Find interactive componentstap(instance)- Simulate touch eventsenter(instance, text)- Simulate text inputexpectNoConsoleWarn()/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/andRNTesterIntegrationTests/(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.