How React Works ?

I am a passionate, athletic, full stack software developer . My aim is to make people's lives better & easier by developing applications and websites.
Hey there π Maaz here , Today we are going to learn how react js work internally.
React is a very popular JavaScript library. With over 5.5 million weekly downloads, React is enjoying great popularity. But not a lot of React developers know how React works under the hood.
In this post, I'll try to uncover some interesting things about React which you, as a React developer, might find fascinating. Let's start at the beginning.
What does React do?
At its very core, React basically maintains a tree for you. This tree is able to do efficient diff computations on the nodes.
Think of your HTML code as a tree. In fact, that is exactly how the browser treats your DOM (your rendered HTML on the browser). React allows you to effectively re-construct your DOM in JavaScript and push only those changes to the DOM which have actually occurred.
JSX is syntactic sugar
There's nothing like JSX - neither to JavaScript, nor to the browser. JSX is simply syntactic sugar for creating very specific JavaScript objects.
When you write something like:
const tag = <h1>Hello</h1>
what you're essentially doing is this:
const tag = React.createElement("h1", {}, "Hello")
You see, when you start writing nested stuff, not only is this difficult to code, but it also becomes very inconvenient to maintain such a codebase. JSX thus helps you bring the cleanliness of HTML to the power of JavaScript.
But what does React.createElement do itself? It creates a plain old JavaScript object. In fact, you can manually call it and see for yourself!
You see, we've an object like this:
{
$$typeof: Symbol(react.element),
key: null,
props: {children: "Hello"},
ref: null,
type: "div"
}
So now you know, once all the JSX is parsed and all the React.createElement calls have been resolved, we land with one giant nested object like above.
React Renderer
Now, if you go back to the point where we start our app, you'll see that in your index.js file, you would find the following line:
// .. prev code
ReactDOM.render(<App />, container)
From above, we know that when <App /> has been done parsing, this is just a huge object of React elements. Then how is React able to construct actual divs and p tags out of it? Meet ReactDOM.
ReactDOM in turn, recursively creates nodes depending on their 'type' property and appends them finally to the DOM.
It should be clear at this point that why decoupling React from the renderers is actually a great move! What React does is, simply construct a tree of UI which could be used not only on web
React Reconciliation
When we say that React maintains a copy of DOM using virtual DOM in JavaScript, and it uses to diff it to any changes and apply it to real DOM, we don't want React to brute-force its way. React, in fact does very lazy reconciliation. React would make the least amount of changes possible, i.e. it would try to re-use elements, attributes, and even styles if possible!
Consider this example:
<img className="class-1" alt="stuff" />
Let's say you change this JSX expression to the below one using some condition or some state:
<img className="class-1" alt="something else" />
Now while diffing, React would see that well, the img tag makes use of the same className both in old and new trees, so why modify it. And it would just modify your alt attribute and move on.
However, there's a catch. Because we don't want React to do a lot of computation on diffing part, React would assume that if a parent has changed, its containing subtree has definitely changed. For example:
<div className="class-1">
<p>I did not change</p>
</div>
If you change this JSX to the below using condition/state:
<p className="class-1">
<p>I did not change</p>
</p>
Although you could see that we don't need to re-create the inner p tag, but React has no way of knowing that while traversing the tree from top (unless, of course you perform heavy tree diffing, which are much expensive algorithms than the heuristic O(n) react follows for diffing). So, React decides to destroy all children (i.e. calling their cleanup functions in useEffect, or componentWillUnmount in class based components) and re-create the children from scratch.
React Keys
When adding/removing elements in a node, React would simply loop over the children in old tree and children in the new tree of the node and mark the places where it needs to perform any addition/removal. But this has a disadvantage without additional help from developer. Consider this example:
<ul>
<li>A</li>
<li>B</li>
</ul>
Consider this is changed to the below by condition/state:
<ul>
<li>Z</li>
<li>A</li>
<li>B</li>
<ul>
Now, when React would start comparing the two lists for difference, it would find the difference at child node 1, would mutate the old A to new Z, then again at child node 2, would mutate it from the old B to new A, and then finally append the new B node.
However, a better way would've been to preserve the existing A and B nodes and just prepend the Z node. But how would React know about that? React keys would help.
Keys just provide a nice way to React to know which elements have changed or not changed while diffing. Now, instead of comparing the whole element, React would compare the keys of the children to see which element needs to be added/removed. The below way is an efficient way of performing the same thing:
<ul>
<li key="A">A</li>
<li key="B">B</li>
</ul>
Now, if this gets changed to:
<ul>
<li key="Z">Z</li>
<li key="A">A</li>
<li key="B">B</li>
</ul>
React would now know that keys 'A' and 'B' already exists, so we just need to add the new element with key 'Z'.
Thank you reading my post β€οΈ




