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:

  1. Configure Yoga stylesupdateYogaProps writes Flexbox properties from ViewProps (such as flexDirection, padding, and dimensions) into yogaNode_.style().
  2. Apply constraints – Minimum and maximum sizes from the parent are converted to Yoga min/max dimension properties.
  3. Execute layout algorithmYGNodeCalculateLayout(&yogaNode_, ownerWidth, ownerHeight, direction) computes the geometry.
  4. Extract metrics – If the node has new layout (yogaNode_.getHasNewLayout()), layoutMetricsFromYogaNode extracts the frame and baseline into a LayoutMetrics struct.
// 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:

  1. StyleSheet.create generates plain objects that become ViewProps in the native layer.
  2. Mounting creates a ViewShadowNode for the container and another for the inner box, both inheriting from YogaLayoutableShadowNode.
  3. updateYogaProps writes flexDirection: 'row', padding: 10, and dimension values into each node's yoga::Node style configuration.
  4. layoutTree executes Yoga calculations, determining the container's frame and positioning the box at (10, 10) with size (50, 50).
  5. FabricMountingManager instantiates native view objects and sets their frames to match the computed LayoutMetrics.

Key Architecture Files

The layout and rendering system spans these critical source files:

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 YGNodeCalculateLayout to determine exact positioning and dimensions.
  • Layout Metrics stored in LayoutMetrics structs propagate through the shadow tree and include critical values like pointScaleFactor for pixel density handling.
  • Fabric Mounting consumes these metrics via FabricMountingManager::executeMount to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →