React is a rich JavaScript framework. I think it's necessary to know a high-level internal working of a language or a framework to use it effectively. React's performance comes from its internal data structures and algorithms. In this article, I will not touch upon the actual codebase, data structures, or algorithms. I will share, on a high level, how React 16 renders and updates the UI. So, let's get started!
Smart data structures and dumb code works a lot better than the other way around. - Eric S. Raymond
During parsing, React creates an in-memory representation of components for easy rendering and updating. Typical React components can have multiple children and sibling components. We have multiple options to represent a component.
https://gist.github.com/subhakundu/15e103ce9dea25c4817ed012740729ff
The following diagram shows the internal representation for the above component using both data structures.
For both the data structures,
One thing to note - I am taking a component for simplicity. I am not taking the entire page into the scope.
There can be two types of rendering - simple rendering without any updates or rendering page components after updates in a dynamic UI. Let's see how each scenario works.
Simple Rendering without Updates
In this case, React can use a combination of Depth-First and Breadth-First Traversal to render the entire component (for both types of representation).
Handling UI Changes
In a dynamic user interface, we will have periodic updates as well as other high-priority activities like network calls. It is possible while rendering current changes, some other high-priority tasks come up. In that case, React may have to do a context switch. And that's where React shines. How does React handle that? Let's jump into that.
[I will use representation and DS (for data structure) inter-changeably.]
Rendering Phase
Let's call the original representation current copy. Let's go step by step.
Let's assume, for our example, Logo, About Us, and Products sub-components have changed after this operation. In that case, the following can be the effects-list.
Why not update the UI while traversal?
Let's suppose, the user creates an animation with tasks A and B. React is supposed to render A and B consecutively for creating a rich experience. Now, a high-priority task has arrived between A and B. Engine cannot ignore it. If the engine has to perform it between A and B by stopping B, the user will see a glitch between A and B. It is not desired user experience.
Why collect updates in a separate DS?
As a high-priority task may arrive in between, rendering may not be as important as that task. In that case, React should switch context. After finishing that task, it can resume the traversal again. This collection of updates will help React to start the operation easily again.
Commit Phase
After the collection of updates in a DS, it's time for applying the changes. It has to go in one shot. Otherwise, the user will see glitches and partial updates.
The above steps complete the entire update cycle. React engine applies various optimizations. We will explore React internals in detail in the next post. I promise I will touch on React data structures and codebase.
If you enjoyed the article, please don't forget to like it. In case you have any doubts, ask in the comment section.
Happy Learning! 😀
Previously published at https://curiouscoder.hashnode.dev/abstract-introduction-to-react-internals