Rendering in React

What is rendering in react ?
React rendering is the process of converting react elements into UI elements that can be displayed on screen .
The react elements are simple javascript object which contains the structure which we want to display / render.
const element = <h1>Hello, React!</h1>;
const reactElement = {
$$typeof: Symbol('react.element'),
type: 'div',
key: null,
ref: null,
props: {
children: 'Hello, React!'
},
_owner: null,
_store: {}
}
Key Details
$$typeof
: Identifies it as a React elementkey
: Used for list renderingref
: Reference to a DOM element or component_owner
: Internal React property tracking component hierarchy_store
: Internal optimization object
These JavaScript objects are obtained from react elements using React.createElement()
function calls by transpilers like Babel, therefore this abstraction layer provides a declarative way to describe UI and separates description and rendering logic unlike direct dom manipulation.
// Equivalent React.createElement() call
const element = React.createElement('h1', null, 'Hello, React!');
React elements are immutable objects and each update creates new react element (js object tree using diffing algo) for easy comparison.
// Initial element
let counter = {
type: 'div',
props: {
children: 'Count: 0'
}
};
// New element (creating a new object, not modifying)
counter = {
type: 'div',
props: {
children: 'Count: 1'
}
};
Whenever any event triggers, react collects all the state updates, batches together and creates new virtual DOM Tree, unlike immediate rendering by DOM.
// Inefficient
function updateUI() {
// Each update triggers immediate DOM manipulation
document.getElementById('count').textContent = newCount;
document.getElementById('status').className = newStatus;
}
function Counter() {
const [count, setCount] = useState(0);
const [clicked, setClicked] = useState(false);
const handleClick = () => {
// Multiple state updates in a single event handler
setCount(c => c + 1); // Update 1
setClicked(true); // Update 2
// React will batch these updates together
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
Therefore, react Elements are more efficient because there is no immediate rendering, it collects multiple state updates on an event and process together instead multiple immediate DOM manipulation for the same event and it only updates what has changed by comparing previous virtual DOM tree with new Virtual DOM, it's able to do because react elements are immutable objects and each update creates new react element
Therefore when state changes new virtual Dom tree ,compares with the previous virtual dom tree, calculate minimal change and efficiently updates real Dom. This is called react's reconciliation process.
Virtual DOM is a Tree-like structure of React elements. It's essentially a JavaScript object that mirrors the structure of the real DOM, but is much faster to manipulate.
HTML vs DOM vs Virtual DOM Object
HTML Representation
//css
<style>
#user-profile {
background-color: blue;
color: white;
padding: 10px;
}
</style>
// html
<div
id="user-profile"
class="profile active"
data-user-id="123"
>
<h2>John Doe</h2>
</div>
//Javscript
<script>
const divElement = document.getElementById('user-profile');
divElement.addEventListener('click', () => {
console.log('Div clicked');
});
console.log(divElement.offsetWidth); // Rendered width
console.log(divElement.clientHeight); // Inner height
</script>
Abstract Representation of a DOM element object contains basically these 5 properties -
{
nodeType: 1, // Always exists for elements
tagName: 'ELEMENT_TAG', // Tag name of the element (e.g., 'DIV', 'H1')
attributes: NamedNodeMap {}, // Attribute collection (empty if no attributes)
childNodes: NodeList [], // List of children (empty if no children)
parentNode: Element || null // Parent node (null for <html>)
}
{
nodeType: 1, // Element node type
tagName: 'DIV',
nodeName: 'DIV',
// Identification Properties
id: 'user-profile',
className: 'profile active',
// Attributes Collection
attributes: NamedNodeMap {
'id': {
name: 'id',
value: 'user-profile'
},
'class': {
name: 'class',
value: 'profile active'
},
'data-user-id': {
name: 'data-user-id',
value: '123'
}
},
// Custom Data Attributes
dataset: {
userId: '123'
},
// Style Properties
style: CSSStyleDeclaration {
backgroundColor: 'blue',
color: 'white',
padding: '10px',
// Many other inherited CSS properties
},
// Event Listeners
_listeners: {
click: [
{
type: 'click',
listener: () => {
console.log('Div clicked')
},
capture: false
}
]
},
// Child Node Relationship
childNodes: [
{
nodeType: 1,
tagName: 'H2',
textContent: 'John Doe',
// Additional H2 element properties
}
],
// Parent-Child Methods
appendChild: [Function],
removeChild: [Function],
insertBefore: [Function],
// Dimensional Properties
offsetWidth: 0, // Will be calculated when rendered
offsetHeight: 0,
clientWidth: 0,
clientHeight: 0,
// Positioning Properties
offsetTop: 0,
offsetLeft: 0,
// Traversal Methods
querySelector: [Function],
querySelectorAll: [Function],
// Event Methods
addEventListener: [Function],
removeEventListener: [Function],
// Inheritance
__proto__: HTMLDivElement.prototype
}
React Element JS Object
// React equivalent (Lightweight)
{
type: 'div',
props: {
id: 'user-profile',
className: 'profile active',
style: {
backgroundColor: 'blue',
color: 'white',
padding: '10px'
},
'data-user-id': '123',
children: [
{
type: 'h2',
props: {
children: 'John Doe'
}
}
]
}
}
Hence,
Abstraction layer which provides declarative way to describe UI and separates rendering logic using React.createElement()
the immutability of react element objects for comparision and optimization,
and light weight object representation makes React rendering more efficient.
There are ways in which rendering can be made more efficient using Memoization, LazyLoading and code splitting. We will discuss this in next post.
Subscribe to my newsletter
Read articles from Nitish Jha directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
