Core Concepts
Shadow Tree
The shadow tree is an immutable tree of shadow nodes that represents the structure and properties of your UI. This tree exists in C++ and serves as the single source of truth for the UI state.Shadow Nodes
Shadow nodes are immutable objects defined inReactCommon/react/renderer/core/ShadowNode.h:
- Immutability - Once created, shadow nodes never change; mutations create new nodes
- Structural sharing - Unchanged subtrees are shared between versions
- Layout cache - Yoga layout results are cached on nodes
- Type safety - Strongly typed props specific to each component type
Shadow Node Family
Each shadow node belongs to a “family” that identifies the component instance across revisions:- Maintains component identity through re-renders
- Enables React’s reconciliation across shadow tree updates
- Links shadow nodes to their JavaScript component instances
Component Descriptors
Component descriptors are factories for creating and cloning shadow nodes of specific types. They’re defined inReactCommon/react/renderer/core/ComponentDescriptor.h.
Each native component (View, Text, Image, etc.) has a descriptor that:
- Creates shadow nodes with the correct concrete type
- Parses and creates typed Props objects
- Manages component-specific State
- Handles event emission
ComponentDescriptorRegistry maintains all available descriptors and looks them up by component name.
Props
Props are immutable, type-safe property bags that configure shadow nodes:- Strongly typed - Each component has its own Props struct
- Codegen-generated - For custom components, Codegen creates Props definitions
- Efficient - Only changed props are serialized across the JSI boundary
- Platform-specific - Can include platform-specific properties
State
State represents native-managed state for a component, separate from React state:- Image loading state - Track image load progress
- Text layout - Cache measured text dimensions
- Scroll position - Native scroll state
- Native animations - Animation progress
Event Emitters
Event emitters handle communication from native back to JavaScript:- Discrete - High priority events like press, focus (sync to next frame)
- Continuous - Scroll, drag, mouse move (batched and throttled)
- AsynchronousBatched - Default, batched with event loop
Rendering Pipeline
Fabric’s rendering pipeline consists of three main phases:1. Render Phase
Executes on the JavaScript thread:UIManagerBinding (exposed to JavaScript via JSI):
createNode()- Create new shadow nodescloneNode()- Clone nodes with updated propsappendChild()- Build tree structurecompleteRoot()- Commit the tree
2. Commit Phase
Executes on background thread, coordinated by theShadowTree:
Layout Calculation
Yoga (Facebook’s flexbox implementation) computes layout:- Runs on any thread (typically background)
- Cached results reused for unchanged subtrees
- Supports measure functions for text and images
- Returns pixel-perfect layouts
Commit Hooks
Commit hooks allow intercepting the commit process:- Pre-commit hooks - Modify tree before layout (e.g., Animation Backend)
- Post-commit hooks - Process results after layout
ReactCommon/react/renderer/uimanager/UIManagerCommitHook.h.
Diffing
TheDifferentiator compares old and new shadow trees:
- Generates minimal set of mutations
- Handles insertions, deletions, updates, reordering
- Optimized for common patterns (append, prepend)
- Output is a
MountingTransaction
3. Mount Phase
Executes on the UI thread:MountingCoordinator delivers transactions to the platform:
- iOS -
RCTMountingManagerapplies mutations to UIViews - Android -
MountingManagerapplies mutations to Android Views
UIManager
TheUIManager orchestrates the entire rendering system. Defined in ReactCommon/react/renderer/uimanager/UIManager.h:
- Manages multiple shadow trees (one per React root/surface)
- Coordinates commits across shadow trees
- Applies mutations via delegates
- Integrates with animation backend
- Manages component descriptor registry
Surface Management
A “surface” is a React root rendered into a native view hierarchy. Each surface:- Has its own
ShadowTree - Has a unique
SurfaceId - Can be mounted/unmounted independently
- Supports different display modes (visible, suspended, hidden)
- Native navigation with React screens
- Modal overlays
- Native UI with embedded React content
Synchronous Layout
One of Fabric’s major improvements is synchronous layout measurement:- Layout is calculated in C++, accessible to JavaScript via JSI
- No asynchronous bridge round-trip
- Cached results returned instantly
- Positioning tooltips and popovers
- Measuring text before render
- Implementing custom layouts
- Avoiding layout flicker
Runtime Shadow Node Reference Updates (RSNRU)
RSNRU is an optimization that keeps React’s references to shadow nodes fresh. FromReactCommon/react/renderer/core/__docs__/RSNRU.md:
RSNRU ensures React always holds references to the latest shadow node revisions, even after they’re cloned internally by Fabric operations like layout or state updates.
- Better layout cache hits - React reuses computed layouts
- Fresh native state - State updates visible to React
- Fewer re-layouts - Avoids redundant layout calculations
- Shadow nodes can be cloned by native operations (layout, state updates)
- When cloned, RSNRU updates wrapper objects held by React
- React’s next render uses the latest revision
- Layout cache and state remain fresh
Concurrent React Support
Fabric is designed for Concurrent React features:Priority-Based Rendering
Different updates have different priorities:- Synchronous - User input, critical updates
- Default - Most state updates
- Idle - Analytics, logging
RuntimeScheduler processes tasks by priority:
Interruptible Rendering
Low-priority work can be interrupted:- Start rendering a low-priority update
- High-priority event occurs (user input)
- Pause low-priority work
- Process high-priority update immediately
- Resume or discard low-priority work
Time Slicing
Long renders are broken into chunks:- Render for 5ms
- Yield to handle input
- Resume rendering
- Prevents blocking user interactions
Platform Integration
iOS (Objective-C++)
RCTSurfacePresenter- Manages surfaces and mountingRCTMountingManager- Applies mutations to UIViewsRCTScheduler- Coordinates React rendersRCTComponentViewRegistry- Maps tags to UIViews
Android (JNI/C++)
FabricUIManager- Java interface to C++ UIManagerMountingManager- Applies mutations to Android ViewsReactInstanceManager- Manages React instancesViewManagerRegistry- Component view managers
Performance Characteristics
Fabric delivers significant performance improvements:Startup Performance
- Faster initialization - C++ components initialized once
- Lazy mounting - Views created only when needed
- Shared layout engine - Yoga shared across components
Runtime Performance
- Synchronous operations - No bridge serialization delays
- Efficient diffing - Minimal mutation sets
- Layout cache - Computed layouts reused extensively
- Priority scheduling - Important updates processed first
Memory Usage
- Structural sharing - Unchanged subtrees shared
- Copy-on-write - Only changed nodes allocated
- Smart pointers - Automatic memory management
Debugging Fabric
Enable Fabric Logs
iOS:Inspector Integration
Fabric integrates with React DevTools:- Inspect shadow tree structure
- View props and state
- Measure layout
- Track renders and commits
Performance Profiling
Use native profilers:- Xcode Instruments - Time Profiler, Allocations
- Android Studio Profiler - CPU, Memory, Frame rendering
- React DevTools Profiler - Component render times
Migration from Legacy Renderer
Enabling Fabric
React Native 0.68+ uses Fabric by default. To ensure it’s enabled: iOS Podfile:Component Compatibility
Most built-in components work with Fabric. Custom native components need:- Component descriptors - Define in C++
- Codegen specs - TypeScript/Flow component spec
- View managers - Update for Fabric APIs
Breaking Changes
- setNativeProps removed - Use state updates instead
- findNodeHandle deprecated - Use refs directly
- UIManager methods changed - Some APIs removed or modified
- Timing differences - Synchronous operations may change timing
Best Practices
Optimize Re-renders
Minimize shadow tree churn:Use React.memo
Prevent unnecessary component updates:Batch State Updates
Multiple updates in same task are batched:Avoid Layout Thrashing
Don’t interleave layout reads and writes:Further Reading
Threading Model
Understand Fabric’s threading architecture
TurboModules
Learn about native modules in new architecture
JavaScript Interface
JSI fundamentals powering Fabric
Codegen
Generate component specs