Let’s explore Fiber, introduced starting with React v16.

React previously used a mechanism called the Stack Reconciler.
Put simply, it detects changes through recursion and applies updates all at once.
This approach is very intuitive, but it had a few problems.
If we describe React v15’s approach in a bit more detail, it largely proceeds in two phases.
rendercomponentDidMountIn other words, step 1 computes what should be reflected in the DOM -> step 2 actually applies it and runs side effects.
The biggest issue with this approach is that the entire sequence runs synchronously. React is ultimately a JavaScript library, which means it runs on a single thread. With that in mind, an approach that updates all changes at once is bound to run into problems. Because applying updates—reflecting UI changes—means occupying the call stack. And if that work is large, it also means other tasks are blocked during that time.
Quantitatively, browsers are generally said to need to process an update within 60fps (about 16.7ms) for users to perceive it as smooth and uninterrupted.
Reference: dev.to
But if the work is so large that it exceeds this budget, users experience a kind of stutter (janky) behavior.
Also, because this mechanism did not support priority updates—which later became central to Concurrent Mode—more important updates could not be processed first. For example, important updates that require immediate feedback, like user input, could be blocked.
Start user input
|
v
Initiating a large DOM update
|
v
User input is blocked until the large DOM update is complete.
The React team was also aware of how serious these issues were, and to solve them and build a better React, they introduced a new reconciler starting with v16. The core goals the React team set were as follows:
Reference: React member GitHub
Process work according to appropriate priorities (run urgent work such as animations first)
For priority comparison, React uses the Lanes model rather than simple numeric comparison.
Thanks to the bitmask, multiple priorities can be preserved simultaneously within a single integer.
Even if there are many pending updates, React can determine the highest-priority work to run now in constant time.
Pause work and resume it later (to avoid exceeding the browser’s frame budget)
Abort/cancel work that is no longer needed
Reuse previously completed work results (to reduce unnecessary computation)
The core of Fiber is splitting render work into small units of work and delegating each unit to a Lanes-based scheduler to avoid blocking the main thread. By slicing work into multiple pieces and yielding control back to the browser between units, React approaches solving the issues above.
More specifically, instead of traversing the entire tree all the way down in one go, Fiber repeats a process of going down in small steps and then coming back up while performing work. When I first read this sentence, I had two questions.
To understand this better, you need to know exactly what “going down” and “coming back up” mean.
Going down (begin phase)
Coming back up (complete phase)
An everyday analogy is like cleaning a house: instead of cleaning the whole house in one go, you clean one room at a time, pausing to check if a guest has arrived, or if an urgent phone call comes in, you handle that first.
In summary, it’s not just reading a unit by going down and then up—it reads while going down, and once that work is done, it considers whether it should proceed to the next unit (whether enough time remains, whether there is higher-priority work, etc.). This way, rather than continuously occupying the main thread by immediately running the next unit, React yields control back to the browser in between. That allows the browser to handle interactions or higher-priority work first, improving perceived performance for users.
So we can answer question 1 like this:
Summarizing the above, Fiber operates based on two core ideas:
In this section, we’ll take a closer look at how Fiber is structured and how it operates.
A fiber node (one unit of work) is implemented as a JavaScript object and contains information about a specific component (or DOM element). Fiber nodes form a tree in the shape of a linked list, expressing parent-child and sibling relationships via pointers such as child, sibling, and return. Thanks to this structure, React can traverse the tree using iteration or traversal algorithms instead of recursion, and it can pause or resume work at the necessary times.
A fiber node is structured as follows.
| Field | Type | Role / Notes |
|---|---|---|
type | Function | string | Component function/class or host tag like |
key | string | null | Unique sibling identifier during list diff |
| Fiber | null | DFS traversal pointers:
|
lanes |
| Priority bits assigned to this node |
childLanes | Lanes | OR'ed lanes of subtree for O(1) skip checks |
| SideEffectFlags | Side effects to run in commit phase |
| any | Cache of previous render result |
pendingProps | any | New props for current render |
alternate | Fiber | null | Double buffering structure: Current tree |
참고 React 18부터 기존
pendingWorkPriority숫자 필드는 사라지고,lanes·childLanes비트마스크가 모든 우선순위 정보를 담습니다.
Below is a very simple visualization of Fiber’s mechanism.
In summary, the React Fiber architecture is a crucial improvement introduced by React to enhance user experience and optimize performance. In particular, Fiber splits work into small pieces and assigns priorities so that urgent work can be processed first. It also minimizes frame drops even when handling long tasks, providing a smoother UI.