skip to content

Fabric Renderer

Fabric builds an immutable C++ shadow tree from React elements, runs Yoga layout on it and mounts only the diff, so layout reads become synchronous. Interviewers probe what that enables.

part ofReact Nativeoverview, primer and where to startread it →
on this pageshow

explore

questions

4

In React Native, what is the Fabric renderer, and what does it enable that the legacy renderer could not?

level: juniorimportance: must knowfreq 60%

answer

  1. the New Architecture's renderer
  2. written once in C++
  3. immutable shadow tree
  4. layout readable synchronously
  5. Suspense and Transitions work

basics

~20 s

Fabric is React Native's New Architecture renderer: a shared C++ core that turns React's tree into native views through an immutable shadow tree. It enables synchronous layout reads, concurrent features such as Transitions and Suspense, and flattening on both platforms.

solid answer

~40 s

Fabric is the renderer of React Native's New Architecture and, since 0.82, the only one. Its core is written once in C++ and shared across platforms. For each host component React renders it creates an **immutable shadow node**, runs **Yoga** layout on the resulting tree and mounts only the diff as native views; React drives it directly through JSI. Because the tree is immutable and lives in C++, layout can be read **synchronously** (so `useLayoutEffect` can position a tooltip before it is shown), several versions of the UI can be in progress at once, which makes **Transitions**, **Suspense** and interruptible rendering work, and updates are automatically batched. It also brings view flattening to iOS, which the legacy renderer only did on Android.

go deeper

for a junior

Say what Fabric is: the New Architecture's renderer, written in C++, turning React components into real native views.

for a middle

Explain the immutable shadow tree and connect it to synchronous layout reads, automatic batching and concurrent features such as Suspense.

for a senior

Use Fabric's guarantees in design: position overlays in useLayoutEffect, rely on Transitions for heavy screens, and know which behaviors changed for old libraries.

for a principal

Weigh the platform consistency of a shared C++ renderer against the cost of libraries that still depend on legacy rendering internals.

## What a renderer does in React Native React itself does not know how to draw anything. A **renderer** takes the tree of elements React produces and turns it into something on screen: ReactDOM turns it into DOM nodes, and React Native's renderer turns it into **host views**, the real platform views such as `android.view.ViewGroup` and `UIView`. **Fabric** is React Native's renderer in the New Architecture. It replaced the legacy renderer, which was implemented separately for each platform, talked to native code over the asynchronous bridge, and kept a single mutable copy of the UI in the native view hierarchy. Since React Native 0.82 Fabric is the only renderer. ## How Fabric is built - **A shared C++ core.** The renderer's logic (shadow trees, layout, diffing) is written once in C++ and runs the same way on iOS, Android and other supported platforms, instead of being re-implemented per platform. - **An immutable shadow tree.** For every host component React renders (`View`, `Text`, `Image`), Fabric creates a C++ **shadow node**. Nodes are never edited in place: an update clones the changed nodes into a new tree and shares the rest. - **Yoga for layout.** The flexbox engine computes each node's size and position on the shadow tree before anything is mounted. - **JSI to React.** React calls into the C++ renderer directly through JSI, synchronously, instead of sending serialized messages. ## What that design enables | Capability | Why it depends on Fabric | |---|---| | **Synchronous layout reads** | Layout lives in the C++ shadow tree, so `measure` or `getBoundingClientRect` can answer immediately, for example inside `useLayoutEffect` | | **Concurrent React features** | Immutable trees let React keep several versions of the UI in progress, so **Transitions**, **Suspense** and interruptible rendering work | | **Automatic batching** | Several state updates render as one commit, so fewer intermediate states reach the screen | | **Prioritized updates** | An urgent update, such as a response to a tap, can interrupt a low-priority render | | **View flattening on both platforms** | Layout-only views are removed from the host hierarchy by the C++ core; the legacy renderer did this only on Android | | **Consistency** | One C++ implementation means fewer platform-specific rendering differences | The legacy renderer could not offer the first four because it kept one mutable copy of the UI in native code and could only be updated through asynchronous messages. There was no way to read layout synchronously and no way to keep an alternative version of the tree while the current one stayed on screen. ## What stays the same 1. You write the same components: `View`, `Text`, `Image`, `ScrollView` and your own function components. 2. Styles and flexbox layout keep their React Native semantics; Yoga computed layout before Fabric too. 3. Most apps notice Fabric through behavior (fewer flickers, working `useLayoutEffect`, Suspense) rather than through new APIs. ## Common confusions - **Fabric is not a new UI toolkit.** It still produces native platform views; it does not draw its own pixels. - **Fabric is not the same thing as JSI.** JSI is the C++ interface to the JavaScript engine; Fabric is the renderer built on top of it, alongside Turbo Native Modules. - **Fabric is not optional in current versions.** From React Native 0.82 the New Architecture, and therefore Fabric, cannot be switched off. - **Fabric is not Hermes.** Hermes is the JavaScript engine that runs your bundle; Fabric talks to whichever engine is running through JSI and does not depend on its internals. - **Fabric does not make your JavaScript multi-threaded.** It makes the renderer's data structures safe to use from more than one thread. ## In an interview A junior answer names Fabric as the New Architecture's C++ renderer that turns React's tree into native views. A strong answer adds the one design decision everything else follows from, the **immutable shadow tree**, and one concrete consequence, such as positioning a tooltip correctly in `useLayoutEffect` because layout can now be read synchronously.

  • Why did React Native's legacy renderer not support Suspense and Transitions fully?
    Concurrent features need React to prepare a new version of the UI while the current one stays on screen, and to abandon or interrupt that work. The legacy renderer kept a single mutable copy of the UI in native code, updated through asynchronous messages, so there was nowhere to hold an alternative tree. Fabric's immutable shadow trees make several in-progress versions possible.
  • In React Native, is Fabric the same thing as JSI?
    No. JSI is the C++ interface that lets JavaScript and native code call each other directly. Fabric is the renderer that uses JSI to receive React's updates, and Turbo Native Modules are the module system that uses it too. JSI is the foundation; Fabric is one of the systems built on it.

saying these in an interview costs you the question

  • Fabric draws its own pixels instead of creating native platform views.
  • Fabric and JSI are two names for the same thing.
  • Fabric is an optional renderer you can still switch off in 0.87.
  • Fabric makes React Native run JavaScript on several threads.
  • View flattening existed on iOS long before Fabric.
open as a page

In React Native's Fabric renderer, what happens in the render, commit and mount phases after a component's state changes?

level: middleimportance: should knowfreq 40%

basics

~20 s

Render clones the changed host components' shadow nodes into a new immutable tree. Commit runs Yoga layout and promotes it as the next tree. Mount diffs it against the tree on screen and applies only the resulting mutations to native views.

open as a page

In a React Native 0.87 note-taking app, how do you position a tooltip under its anchor before the first frame is shown, without a flicker?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Measure the anchor's host View ref inside useLayoutEffect with getBoundingClientRect or measureInWindow, then set the tooltip's placement there. Fabric answers synchronously from the committed shadow tree, so the corrected position commits before the first frame.

open as a page

In React Native's Fabric renderer, what is view flattening, and when do you need collapsable={false} on a View?

level: middleimportance: nice to knowfreq 25%

basics

~10 s

View flattening lets Fabric skip creating native views for layout-only Views, folding their layout into their children during diffing. Set collapsable={false} when native code needs that View to exist as a real platform view.

open as a page