Thread Overview
React Native applications typically use four main threads:1. JavaScript Thread
Executes all your JavaScript code:- React rendering - Component renders and reconciliation
- State updates - Processing setState and hooks
- Event handlers - Button presses, input changes, etc.
- Business logic - App-specific computations
- Redux/state management - State transitions
- Async operations - Promise chains, async/await
In the new architecture, this is where JSI enables synchronous calls to native code without thread switching.
2. UI Thread (Main Thread)
The native platform’s main thread:- View rendering - Drawing pixels to screen
- Layout application - Positioning views
- User input - Touch events, keyboard input
- Animations - Native animation execution
- View mutations - Creating, updating, destroying views
- Platform APIs - iOS UIKit, Android View system calls
3. Shadow Thread (Background Thread)
Handles layout computation in Fabric:- Yoga layout - Flexbox calculations
- Shadow tree operations - Cloning, diffing shadow nodes
- Commit phase - Processing React commits
- Diffing - Generating mutation lists
- UI thread stays responsive during layout
- Complex layouts don’t block user interaction
- Can compute layout for upcoming screens
4. Native Modules Background Threads
TurboModules can specify thread requirements:- Network requests - HTTP calls, downloads
- Database operations - SQLite queries
- File I/O - Reading/writing files
- Image processing - Decoding, resizing
- Heavy computations - Cryptography, compression
Threading in the New Architecture
JSI and Synchronous Calls
With JSI, JavaScript can call native code synchronously:RuntimeExecutor
TheRuntimeExecutor safely schedules work on the JavaScript thread from any thread. Defined in ReactCommon/runtimeexecutor/ReactCommon/RuntimeExecutor.h:
- Thread safety - Runtime access serialized
- Non-blocking - Posts to queue, doesn’t wait
- Error handling - Exceptions caught and reported
CallInvoker
TurboModules useCallInvoker for thread management:
Event Loop Integration
The JavaScript thread implements an event loop aligned with web standards. FromReactCommon/react/renderer/runtimescheduler/__docs__/README.md:
Event Loop Phases
Each tick of the event loop:- Select Task - Choose next task by priority
- Execute Task - Run the task’s JavaScript/C++ callback
- Process Microtasks - Drain microtask queue (Promises, queueMicrotask)
- Update Rendering - Flush UI updates to host platform
Atomicity of UI Updates
Each event loop tick produces one atomic UI update:- Predictable - UI updates happen at well-defined points
- Atomic - No partial updates visible to user
- Aligned with web - Same semantics as browsers
Task Priorities
RuntimeScheduler supports priority-based scheduling:
Fabric Rendering Pipeline Threading
Phase 1: Render (JavaScript Thread)
- React reconciliation
- Call Fabric UIManager via JSI
- Create/clone shadow nodes
- Build new shadow tree
Phase 2: Commit (Background Thread)
- Run commit hooks
- Calculate layout (Yoga)
- Diff shadow trees
- Generate mutation list
Phase 3: Mount (UI Thread)
- Apply mutations to views
- Create/update/delete native views
- Set view properties
- Update layout
Thread Coordination
TurboModule Threading
Synchronous Methods
Execute on JavaScript thread:Asynchronous Methods
Can run on any thread:Specifying Thread Requirements
iOS - require main thread:Animation Threading
JavaScript-Driven Animations
- Animation ticks on JavaScript thread
- Each tick triggers Fabric render
- Can drop frames if JS thread busy
Native-Driven Animations
- Animation runs on UI thread
- Bypasses JavaScript thread entirely
- Smooth even if JavaScript thread blocked
Animation Backend
FromReactCommon/react/renderer/animationbackend/__docs__/AnimationBackend.md:
The Animation Backend allows animation frameworks to update props without going through React:
- Layout animations on shadow thread
- Non-layout animations on UI thread
- JavaScript thread not involved
Event Handling Threading
Event Emission
Native to JavaScript:Event Priorities
FromReactCommon/react/renderer/core/EventEmitter.h:
- Discrete: Press, focus, blur
- Continuous: Scroll, drag, mouse move
- AsynchronousBatched: Most custom events
Event Beat
Synchronizes events with rendering:Thread Safety Best Practices
1. Never Share JSI Values Across Threads
2. Use RuntimeExecutor for JavaScript Thread Access
3. Protect Shared State with Mutexes
4. Prefer Immutable Data Structures
5. Use Weak Pointers to Avoid Cycles
Debugging Threading Issues
Detect Thread Violations
iOS:Thread Sanitizer
Enable ThreadSanitizer to detect races: Xcode:- Edit Scheme
- Run tab
- Diagnostics
- Enable “Thread Sanitizer”
Logging Thread IDs
Xcode Instruments
- Time Profiler - See which threads are busy
- System Trace - Visualize thread activity
- Thread States - Identify blocked threads
Performance Optimization
Minimize Thread Switching
Batch UI Updates
Offload Heavy Work
Use requestIdleCallback
Further Reading
Architecture Overview
See how threading fits in the architecture
JavaScript Interface
JSI and thread safety
Fabric Renderer
Fabric’s multi-threaded rendering
TurboModules
Threading in TurboModules