Basic concepts of JSX and Virtual DOM every React JS developer should know

JSX and Virtual DOM are the two main concepts of React JS that powered React JS to reach its unique stage. Today we will discuss these two concepts in brief.



What is JSX?

JSX is an acronym of JavaScript XML. JSX is nothing but a syntactic sugar of creating React Element. It allows us to write HTML-like syntax in JavaScript function.



Why JSX?

Before going into detail about why JSX is used, let’s take a look at how HTML renders by the browsers.

We all know that browsers can only understand HTML code. But how does the browser run the HTML code under the hood and display the amazing pages? Basically, when the browser renders the HTML code, it passes them through HTML parser and creates an object-like structure called DOM tree (DOM stands for Document Object Model). The next step of rendering is Attachment. In the attachment phase, all the style rules are attached with DOM tree and sent to the Render tree. Finally, Render tree pains the element on the screen, and we can see them.

When browser converts the HTML to DOM tree, it used a document method called createElemet() for every HTML element. For example –

const root = document.getElementById("root");
const h2 = document.createElement("h2");
h2.innerText = "Hello, world!";
root.appendChild(h2);

In the above code, first, we have created an HTML element using document.createElement() method. The browser does the same for every HTML element on the page while parsing a page. When browser’s HTML parser finds any HTML element, it converts it to DOM element using document.createElement method. So, HTML is nothing but a syntactic sugar of createElement method, which allows us to create elements simply and concisely.

Similarly, React JS has a virtual DOM. It needs to create React Elements for its virtual DOM. We can create react elements using React.createElement method. But it is tedious to create multiple or nested elements by calling the React.createElement method again and again. JSX made a developer’s life easy and simple by enabling us to create react elements using simple HTML-like syntax. See the following examples –

To display hello h2 (wrapped in h2) and hello h3 (wrapped in h3) on the web page under root div using React.createElement we have to write –

const root = document.getElementById("root");

// Only using React.createElement
const element =  React.createElement('div', null, [
   React.createElement("h2", null, "Hello h2"),
   React.createElement("h3", null, "Hello h3"),
]);

ReactDOM.render(element, root);

But we can do the same using JSX like the following –

const root = document.getElementById("root");

// Using JSX
const element = <div>
   <h2>Hello h2</h2>
   <h3>Hello h3</h3>
</div>

ReactDOM.render(element, root);



Virtual DOM and Diffing algorithm

We have discussed the browser DOM in short in the JSX section. React JS stands on an idea of something similar to browser DOM called virtual DOM. Virtual DOM is a mirror copy of browser DOM. When we run a react app in the browser, React JS creates a copy of the browser DOM and holds it in the memory.

The reason React creates a virtual DOM is to identify any change of state on the DOM elements and update it to the UI quickly and efficiently.
When we change any element in the browser DOM, it needs to re-render the whole DOM tree. Modern single-page applications can have hundreds of thousands of states. Sometimes, it is costly to detect any state change and update the UI accordingly. React brought a revolution in this case of handling vast amounts of state very quickly and efficiently.

How actually React JS handle this using virtual DOM? Well, let me explain.

As I have mentioned earlier, React creates a virtual representation of browser DOM when the application renders for the first time on the browser. If any of the elements or states change in the page, react create another copy of the previous virtual DOM without re-rendering the browser DOM and compare the changes between the previous virtual DOM and newly created virtual DOM using diffing algorithm. React made it very efficient and quick to find out the difference between them because there is no UI painting involved there. After identifying the difference, React only update the differents part of the browser DOM without re-rendering the whole page.

Though React is not the best solution for all use cases, it performs better compared with vanilla JS or using jQuery, where needs to deal with a massive number of states like SPA because of its virtual DOM concepts. So we should keep a clear-cut concept of React virtual DOM as a React JS developer.


Source link

Monster 1.26.0 released

Today we released the latest edition of our Monster project. Monster is a collection of javascript classes that we need for daily work in our web projects.

Besides small helper functions and classes, it also provides useful functions to enable reactive programming.

Monster is available via jsdelivr and npm.

Only the changes are described here. The full functionality can be found in the documentation.



Node

There is now a new Node class. With it, trees, can be mapped.

import Node from 
'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.0/dist/modules/type/node.js';

const node = new Node('hello!');
console.log(node.value); // ↦ hello!



NodeList

The NodeList class extends the internal Set class with a check for nodes, so that you can be sure that only nodes are in the set.

import NodeList from 
'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.0/dist/modules/type/node.js';

const node = new NodeList();
node.add(1); // ↦ Error



NodeRecursiveIterator

This new class implements a recursive iterator. This allows all nodes of the tree to be looped through.

import NodeRecursiveIterator from 
'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.0/dist/modules/type/noderecursiveiterator.js';

// 1
// 2
// ├ 2.1
// ├ 2.2
// └ 2.3
// 3
// 4
// ├ 4.1
// └ 4.2

new Node('1').appendChild(
  (new Node('2'))
        .appendChild(new Node('2.1'))
        .appendChild(new Node('2.2'))
        .appendChild(new Node('2.3')))
  .appendChild(new Node('3'))
  .appendChild(new Node('4')
        .appendChild(new Node('4.1'))
        .appendChild(new Node('4.2')));

const iterator = new NodeRecursiveIterator(node);

const result = [];
// here we are now running through the tree structure
for (const n of iterator) 
  result.push(n.value);


// ↦ ['1', '2', '2.1', '2.2', '2.3', '3', '4', '4.1', '4.2']




buildTree Function

This function brings everything together. Based on the function buildMap this function creates a NodeList which contains all values from a dataset.

buildTree(subject, selector, id, parentID, filter)

subject is the dataset that came from a REST API, for example. The selector is used to select the desired entries. id and parentID define which keys are to be taken as ID and reference to the parent dataset, respectively. filter finally allows the data length to be filtered.

// dataset from API
const objects = 
    dataset: 
        "1": 
            id: "1",
            name: "vehicle",
            parent: null

        ,
        "2": 
            id: "2",
            name: "car",
            parent: "1"
        ,
        "3": 
            id: "3",
            name: "truck",
            parent: "1"
        ,
        "4": 
            id: "4",
            name: "motorcycle",
            parent: "1"
        ,
        "5": 
            id: "5",
            name: "SUV",
            parent: "2"
        ,
        "6": 
            id: "6",
            name: "sports car",
            parent: "2"
        
    


// build a tree with nodes 
const nodes = buildTree(
           objects, 
           'dataset.*', 
           'id',    // key
           'parent' // key );

// issue of the tree with the NodeRecursiveIterator
nodes.forEach(node => 
    new NodeRecursiveIterator(node).forEach(n => 
        console.log("".padStart(n.level*2, '.')+(n.value.name));
    );

);

// vehicle
// ..car
// ....SUV
// ....sports car
// ..truck
// ..motorcycle



I18n Formatter

The new formatter extends the standard text formatter by the possibility to pass a translation.

import Formatter from 
'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.0/dist/modules/i18n/formatter.js';

const translations = new Translations('en')
                .assignTranslations(
                    message: 
          "$animal has eaten the $food!"
                );

new Formatter(, translations).
   format("message::animal=dog::food=cake");
// ↦ dog has eaten the cake!     



Fixes

  • updater: replaces more than one sub path

hope you enjoy it!



References


Source link