kReact: Building your own React & Virtual DOM
Let’s learn React by building react within 100 lines of code
In this blog, we will build a library similar to react and understand how React works internally. This blog is written in a way that even if you don’t know react or want to learn the internal working of react, you would find it useful.
Link to the GitHub Repository: https://github.com/git-kamesh/kReact
Follow me on Twitter: @kamesh_koops
[REQ] Requirements & Use-cases: What do we want to build? 🤔
- [COMPONENT] Able to split complicated UI’s into smaller reuseable components (Button, DropDown, ImageSlider, etc ).
- [JSX] Able to write HTML template in JavaScript itself. Let's call this
JSX
. - [LOGIC] JSX should allow to embed JavaScript expressions and logically controlled.
- [PROPS] Able to pass data/information to component from outside, let's call this
props
. - [STATE] Component can have its own data/information without passing to it from outside, let's call this
state
. - [RE-RENDER] Whenever
props
orstate
gets modified, the changes should be reflected to the UI automatically. Let's call thisre-render
. - [PREVENT] Should be explicitly able to prevent
re-render
whenever required. (componentShouldUpdate) - [LIFE-CYCLE] Know components life-cycle events
- [DOM-OPERATION] Should handle DOM operations itself.
- [DIFF] On re-render should find the difference between the old DOM and new Virtual DOM, and only update that part to DOM. Let's call this
patch
.
Let's understand
- Before jumping, we have to understand a few things/concepts like React, DOM, Virtual DOM, JSX, Components, State, JSX Transpiler, Reconciliation.
- Don’t know? don’t worry we will see it here itself.
What is React? 👽
- React is a component-based UI library.
- The component can be anything like Button, DropDown, ImageSlider, PasswordInput, etc.
- Here, components are building blocks of UI and will respond to data change.
- Components allow reusability thus providing development speed, consistency, separation of concern, ease to maintain, and unit testable.
- Also allows both, building an entire application (or) part of an application/Feature.
DOM
- DOM stands for Document Object Model
- It's an object representation of the parsed HTML document
- We could update the dom through DOM APIs (e.g: )
- When a DOM object is updated, the browser runs two expensive operations
- Reflow — Calculates the dimension and position of every element and its children.
- Repaint — Determines visual changes (like color, opacity, visibility) and applies them.
- One of the important advantages of virtual dom is, It helps to reduce unwanted reflow and repaint by updating only the part of the dom which is changed instead of updating the entire dom.
Virtual DOM
- Virtual DOM is nothing but a lightweight in-memory javascript object representation of the actual DOM.
- It mimics an actual DOM.
JSX 101
const element = <h1 className="clrR">Hello, world!</h1>;
- The above tag syntax is neither a string nor HTML. It is JSX.
- JSX stands for JavaScript XML. It is used to define our virtual DOM.
- Just like HTML used for building actual DOM, JSX is used for building virtual DOM.
- JSX in the most simple words is how React allows us to write HTML in JavaScript.
- JSX is a syntax extension for JavaScript and it is not valid JavaScript, web browsers cant read it directly.
- So, if JavaScript files contain JSX, that that file will have to be transpiled. That means that before the file gets to the web browser, a JSX compiler will translate any JSX into regular JavaScript.
- After compilation, JSX expressions become regular JavaScript function calls and evaluate JavaScript objects.
- The above JSX example will be compiled similarly to the below.
React.createElement('h1', { className: 'clrR'}, 'Hello, world!');
Reconciliation
- Whenever a component’s state or props gets updated, the component gets re-rendered and builds a new virtual DOM.
- Then react runs the diffing algorithm to calculate what changes should be applied to real DOM. This process is known as reconciliation.
Terms to understand
- Rendering: Process of converting virtual dom into dom
- Mounting: Process of injecting rendered dom into target dom
- Diffing and Patching: Process of comparing the virtual dom and actual dom, updating the nodes which are changed
Theories over let's play with code 😍
Rendering Logic
render(vnode, parent):
IF vnode IS class component:
CREATE NEW INSTANCE FOR component --> componentInstance
GENERATE component VNODE BY INVOKING componentInstance.render() --> VNode
RENDER VNODE BY PASSING VNODE INTO render FUNCTION --> DOMNode
ELSE IF vnode IS function component:
GENERATE VNODE BY EXECUTING vnode --> VNODE
RENDER VNODE BY PASSING VNODE INTO render FUNCTION --> DOMNode
ELSE IF vnode IS OBJECT:
CONVERT vnode OBJECT INTO DOMNode
RECURSIVELY APPLY render FUNCTION on vnode children
ASSIGN PROPS AS DOMNode attributes
MOUNT DOMNode ON parent
RETURN DOMNode
Patching Logic
patch(dom, vnode, parent):
IF dom AND vnode DIFFED:
RENDER vnode --> DOMNode
REPLACE dom WITH DOMNode
Full source code
GitHub Repository: https://github.com/git-kamesh/
Follow me on twitter: @kamesh_koops
References and Similar articles
- https://maksimivanov.com/posts/virtual-dom/
- https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060
- https://medium.com/@sweetpalma/gooact-react-in-160-lines-of-javascript-44e0742ad60f
- https://reactjs.org/docs/reconciliation.html
- https://www.youtube.com/watch?v=x7cQ3mrcKaY&t=742s&ab_channel=JSConf