How React Native Handles Layout and Rendering Primitives: Shadow Nodes, Yoga, and Fabric Explained
React Native handles layout and rendering primitives through a three-stage pipeline where Shadow Nodes represent the logical component tree, the Yoga engine computes Flexbox-based geometry, and the Fabric mounting layer translates these metrics into native platform views.
React Native's UI architecture, maintained in the facebook/react-native repository, decouples layout calculation from platform-specific drawing by maintaining an intermediate Shadow Tree in C++. This architecture allows JavaScript components to declare Flexbox styles that get computed by the Yoga layout engine and then mounted as native iOS UIViews or Android Views through the Fabric renderer.
Shadow Nodes and the Logical Tree
When a React component renders, the system creates a hierarchy of Shadow Nodes that act as the source of truth for layout calculations. Each native component like <View> corresponds to a concrete subclass of LayoutableShadowNode.
In packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h, the abstract base class stores a reference to its Yoga node via mutable yoga::Node yogaNode_;. Concrete components inherit through ConcreteViewShadowNode as shown in packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.h:
class ViewShadowNode final :
public ConcreteViewShadowNode<
ViewComponentName,
ViewShadowNodeProps,
ViewEventEmitter> {
// View-specific implementation...
};
During rendering, React creates a ShadowNodeFragment containing props and children. The LayoutableShadowNode constructor links this fragment to the Yoga tree, establishing the foundation for subsequent layout calculations.
Yoga Layout Engine and Flexbox Calculations
The actual geometry computation occurs in packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp. The layoutTree method orchestrates the layout pass through four precise steps:
- Configure Yoga styles –
updateYogaPropswrites Flexbox properties fromViewProps(such asflexDirection,padding, and dimensions) intoyogaNode_.style(). - Apply constraints – Minimum and maximum sizes from the parent are converted to Yoga min/max dimension properties.
- Execute layout algorithm –
YGNodeCalculateLayout(&yogaNode_, ownerWidth, ownerHeight, direction)computes the geometry. - Extract metrics – If the node has new layout (
yogaNode_.getHasNewLayout()),layoutMetricsFromYogaNodeextracts the frame and baseline into aLayoutMetricsstruct.
// YogaLayoutableShadowNode::layoutTree implementation
YGNodeCalculateLayout(&yogaNode_, ownerWidth, ownerHeight, direction);
if (yogaNode_.getHasNewLayout()) {
auto layoutMetrics = layoutMetricsFromYogaNode(yogaNode_);
layoutMetrics.pointScaleFactor = layoutContext.pointScaleFactor;
setLayoutMetrics(layoutMetrics);
yogaNode_.setHasNewLayout(false);
}
Child layout propagates recursively through YogaLayoutableShadowNode::layout, which transfers metrics to each child and invokes their layout methods depth-first until the entire tree resolves.
Fabric Mounting and Native Rendering
After Yoga computes the geometry, the ShadowTree reconciles with the Mounting layer to create platform-native views. The FabricMountingManager class in packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp handles this transition.
The executeMount method iterates over affected shadow nodes and applies the computed LayoutMetrics to native view objects:
// FabricMountingManager::executeMount
for (auto &mountItem : mountItems) {
mountItem.execute(this); // Creates or updates native views via JNI
}
React Native does not perform pixel drawing itself. Instead, it translates Yoga-derived geometry into native view frames—UIView on iOS and android.view.View on Android—leaving the actual rasterization to the platform's UI toolkit.
Practical Layout Pipeline Example
Consider this standard React Native component that exercises the entire pipeline:
// MyBox.tsx
import React from 'react';
import {View, StyleSheet} from 'react-native';
export default function MyBox() {
return (
<View style={styles.container}>
<View style={styles.box} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
padding: 10,
backgroundColor: '#eee',
},
box: {
width: 50,
height: 50,
backgroundColor: 'tomato',
},
});
Under the hood, the following sequence occurs:
StyleSheet.creategenerates plain objects that becomeViewPropsin the native layer.- Mounting creates a
ViewShadowNodefor the container and another for the inner box, both inheriting fromYogaLayoutableShadowNode. updateYogaPropswritesflexDirection: 'row',padding: 10, and dimension values into each node'syoga::Nodestyle configuration.layoutTreeexecutes Yoga calculations, determining the container's frame and positioning the box at(10, 10)with size(50, 50).FabricMountingManagerinstantiates native view objects and sets their frames to match the computedLayoutMetrics.
Key Architecture Files
The layout and rendering system spans these critical source files:
packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js– Defines TypeScript/Flow types for layout-related style props includingDimensionValueand Flexbox properties.packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h– Abstract base class holding the mutableyoga::Nodereference.packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.hand.cpp– Implements Yoga configuration, the layout pass algorithm, and metric extraction.packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.h– Concrete view component implementation.packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp– Applies layout metrics to native Android views and coordinates the mounting phase.
Summary
- Shadow Nodes serve as the C++ representation of the React component tree, bridging JavaScript declarations and native layout calculations.
- Yoga Layoutable Shadow Nodes translate style props into Flexbox constraints and execute
YGNodeCalculateLayoutto determine exact positioning and dimensions. - Layout Metrics stored in
LayoutMetricsstructs propagate through the shadow tree and include critical values likepointScaleFactorfor pixel density handling. - Fabric Mounting consumes these metrics via
FabricMountingManager::executeMountto create and position platform-specific native views without React Native directly manipulating pixels.
Frequently Asked Questions
What is the role of Shadow Nodes in React Native layout?
Shadow Nodes act as the intermediate representation between JavaScript components and native platform views. According to the React Native source code, each LayoutableShadowNode maintains a yoga::Node reference and stores layout results in LayoutMetrics, allowing layout calculations to occur on a background thread before any native view creation.
How does Yoga differ from standard browser layout engines?
Yoga is a cross-platform C++ implementation of Flexbox specifically designed for React Native's needs. Unlike browser engines that handle multiple layout modes, Yoga focuses exclusively on Flexbox calculations through YGNodeCalculateLayout, providing deterministic, platform-consistent geometry computation that runs synchronously within the native architecture.
What is the Fabric architecture in React Native?
Fabric is React Native's new rendering layer that replaced the legacy UI manager. It operates through FabricMountingManager to efficiently reconcile shadow trees with native views. The architecture enables priority scheduling, synchronous layout passes, and direct JSI (JavaScript Interface) communication, resulting in improved scroll performance and reduced memory usage compared to the previous asynchronous bridge architecture.
How are layout updates propagated to native views?
Layout updates propagate through a recursive depth-first traversal starting at YogaLayoutableShadowNode::layoutTree. When Yoga determines new metrics, setLayoutMetrics updates the shadow node, which triggers FabricMountingManager::executeMount to create, update, or delete native view objects via the JNI bridge on Android or the Objective-C++ layer on iOS, applying frames calculated by the Yoga engine.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →