React Internals - React Fiber Introduction

Being declarative is a good thing and probably the best about React. But like all good things there are few things that are not so nice about being declarative, because here you as a consumer of the library instruct react about what to do, and not bother about how it actually does it, which then makes it ok not to ever know goes under the hood.

Generally if you use react the way its supposed to be used, you would not need to know how react does what it does for us. But as you write more applications you would realize that understanding some of the internals of react will actually help you to write better code. Use react the way it was intended, rather than use a hack of some sort and then later regret it.

Virtual DOM

Most people while learning react, learn about the fact that when ever there is a state or prop update, the components re-render, and that changes are flushed to the UI(dom), and for obvious performance reasons, react does not always tear down and recreate the dom on every state change. That's when the concept of virtual dom comes in, react on every render creates an immutable tree of react elements from various type of components with the current state and props, whenever there is an update, it creates an updated react element tree. And then runs a diffing algorithm to transform the tree from one state to another.

Please read through the assumptions react makes and a high level take on the diffing algorithm used by react -

React Reconciliation Official Docs React Reconciliation.

This immutable tree of react elements was called the virtual dom before, but now the term is no longer used by the React team in their official documentation. I will call this the react element tree going forward.

Changes in React 16

React also used to keep an internal tree of instances, which are used to track state, in version 16 they introduced the concept of Fiber Nodes.

Fiber nodes constitute the internal tree that tracks state, props and effects.

From the moment state updates inside a component, to the moment actual dom changes, work that react does to achieve it is called reconciliation

This is the primary topic we are going to cover in-depth and in plain English with help of code snippets screenshots and diagrams for better and clear understanding.

Motivation for Fiber Architecture

React adopted the Fiber architecture for performance reasons, earlier the reconciliation process was completely synchronous, but in react fiber the reconciliation process is divided into two phases -

  • Render
  • Commit

We will come to what happens in each phase, but for now just remember that these two phases are asynchronous.
So the earlier issues with long running tasks causing frame drops and making the app laggy no longer exist.

Reconciliation Process - 10,000 Ft view

  • Create the Fiber Root from the root container element (when using ReactDom.render, createRoot is the new way of doing it, not part of this article) -
    fiber root

  • React would create a react element object starting from the top level component

  • For each and every react element(could be functional, class, DOM/Host component etc) there would be a fiber node created and is added to the Fiber tree(you would be surprised that this tree is not actually a tree but a linked list!!)

  • This fiber tree, basically acts as a mutable data structure, which keeps track of work to be performed on each of the fiber node, now work for each element might be different based on the component type, it might be firing component life cycle events, flushing updates to dom, calling a side effect etc.

  • So after the fiber node tree is created, in the render phase, for all the fiber nodes, the react framework, performs the work needed in each of these nodes and traverses the entire tree on child and siblings to make sure all the work defined in each node is performed, remember that no side effects are run during this phase and that these unit of work in each node is asynchronous, can be paused, scraped and redone.

  • Last phase is the commit phase, this is where the post render life cycle events, DOM updates and other side effect which can affect dom directly takes place, this phase hence has to be synchronous.

  • Once the commit phase is done, one cycle of the reconciliation phase is completed.

Below is a high level scribble for when ReactDOM.render is called for the first time and how the reconciliation kicks in.

On a broad level, this shows the initial creation of Fiber root, and then how the fiber tree is created based on the react element objects, and then work is performed on each of the node as part of the render phase.

This is where I stop for this introduction, I will come up with a more in-depth view where I would debug the whole cycle from updating an element and how finally dom changes are triggered and flushed.

But that's for another day, please do leave feedback below.

19