ReactJS - Tout savoir sur le Virtual DOM et la Réconciliation
Tags: react, javascript, webdev, french
Published: 2023-02-17 08:31:17

Dans cet article, nous aborderons le **Virtual DOM** et la **Réconciliation** qui sont des notions peu connues des développeurs **ReactJS**, mais qui pourtant composent le cœur de leur outil. Je vous définirez ces concepts et vous les illustrerez à l’aide d’exemple afin de lever le brouillard une bonne fois pour toutes!

#Sommaire
- [Introduction](#introduction)
- [Virtual DOM](#virtual-dom)
- [Fonctionnement du Virtual DOM dans ReactJS](#work)
- [Stratégie d’optimisation de ReactJS](#strategy)
- [Réconciliation](#reconciliation)
- [Conclusion](#conclusion)

<a name="introduction"></a>
# Introduction
Nombreux sont ceux qui pensent que le secret de la réussite de ReactJS réside dans le fait qu’il utilise le **Virtual DOM** et que ce dernier lui confère une **rapidité** supérieure au DOM! En réalité, ça n’est pas tout à fait vrai. Au grand regret de vous décevoir, React n’est pas “plus” rapide que le DOM. Cela reviendrait à dire qu’il est possible d’aller plus vite que la vitesse de la lumière. Regardons de plus prêt la raison pour laquelle React utilise le Virtual DOM.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjcbz87elh0q8c67w58r.jpg)

Je vous rassure d’avance, si vous ne comprenez pas toutes les notions abordées dans cet article du premier coup, c’est normal. Nous allons entrer dans les entrailles de la bête **ReactJS** afin d’en comprendre son fonctionnement. Prêt à me suivre ? Alors prenez vos lampes torches et allons éclaircir le **Virtual DOM** et la **Réconciliation**! 

<a name="virtual-dom"></a>
# Virtual DOM
Il ne faut pas confondre le DOM et le Virtual DOM. Le **DOM** est une représentation de la structure et du contenu d’une page web. Le navigateur peut manipuler le DOM afin de **modifier l’affichage** d’une page. En revanche, le **Virtual DOM** n’est qu’une **copie** du DOM sous forme d’objet **JavaScript**.

ReactJS est une libraire qui est construite sur le principe de **State Driven UI** (ou interface utilisateur dirigée par les états en bon français). Le **changement d’état** d’un composant entraîne un re-render de l’interface utilisateur. Le composant ainsi que **tous ses enfants** sont alors re-render par le DOM. Dépendamment du nombre d’opérations effectuées par le DOM, cette étape peut être **très coûteuse** ce qui implique de **mauvaises performances**. 

En réalité, React ne va pas demander au DOM de re-render l’intégralité de l’interface utilisateur, il va faire appel au Virtual DOM. Le véritable but du Virtual DOM est de **minimiser le nombre d’opérations** que le **DOM** doit réaliser.

Le Virtual DOM a ainsi deux bénéfices : 
1. Il améliore l’**UX** (expérience utilisateur) en améliorant les performances de l’application.
2. Il améliore la **DX** (expérience développeur) en créant une abstraction dans la manipulation du DOM, permettant de se soucier des problématiques métier et non des problématiques de gestion du DOM. **Pas besoin de se casser la tête à gérer les changements d’état, c’est React qui s’en charge.**

Maintenant que nous avons vu ce qu’est le Virtual DOM en théorie passons à la pratique.

<a name="work"></a>
# Fonctionnement du Virtual DOM dans ReactJS

Comme dis précédemment, le Virtual DOM est un objet JavaScript. Mais à quoi ressemble-t-il ?

Prenons comme exemple le code React suivant :

```javascript
export default function Counter() {
    const [count, setCount] = useState(0);

    return (
        <>
            <p>Ceci est un compteur</p>
            <button onClick={() => setCount((count) => count + 1)}>
                Total : {count}
            </button>
        </>
    )
}
```

Ce code représente l'interface ci-dessous :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bekqeznmttfn0m4mkppd.png)

Vous avez un composant constitué d’un fragment React avec un paragraphe et un bouton. Lorsque vous cliquez sur le bouton, le compteur s’incrémente. 

Il est possible de voir le code ci-dessus comme ceci : 
```javascript
const element = React.createElement(
	React.Fragment,
	null,
	React.createElement("p", null, "Ceci est un compteur"),
	React.createElement("button", null, "Total : 11"),
)
```

Et voilà à quoi ressemble le **Virtual DOM** :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3zoom6b3ew3ihcg4qtz9.png)

J’attire votre attention sur l'attribut typeoff de l’objet ci-dessus :
```javascript
$$typeof: Symbol(react.element)
```

En React, tout élément constituant le DOM est un **React Element**. Ce sont ces éléments qui sont placés dans le Virtual DOM. 

On a donc un **arbre** (le Virtual DOM) qui est composé de **nœuds** (React Element). Si vous avez déjà creusé le sujet, vous savez certainement qu’en réalité, les nœuds ne sont pas vraiment des **React Element** à proprement parler mais des **fibers**. Pour des soucis de simplification nous diront React Element ici. 

Maintenant nous savons ce qu’est le Virtual DOM, à quoi il ressemble, mais on ne sait pas vraiment comment il est utilisé dans ReactJS.

<a name="strategy"></a>
# Stratégie d’optimisation de ReactJS
Nous l’avons dit, le Virtual DOM n’est pas une fonctionnalité de React. Il est plutôt un **outil** permettant de mettre en place la **stratégie d’optimisation**.

Regardons comment fonctionne le procédé de mise à jour de l’interface utilisateur. Il y a deux opérations possibles. Soit on initialise, soit on met à jour.

## L’initialisation
Lors du **premier render**, React créé l’arbre du Virtual DOM représentant l’interface utilisateur et le stock en **mémoire**. 

Dans notre exemple, on aura donc l’arbre suivant :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmp5t0i9b9bug9xobss5.png)

## La mise à jour
Lorsqu’un **état** change dans l’un des **React Element**, une autre version du **Virtual DOM** est créé. On se retrouve donc avec le **current tree** qui est l’ancienne version en mémoire et  l’**updating tree** qui est l’arbre avec les mises à jour demandées.

Dans l’exemple précédent, lorsque l’on clique sur le bouton, on incrémente le compteur “count”. Une nouvelle version de l’arbre est donc générée avec le texte du bouton mis à jour.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzbm1nfail4cgi1c18kw.png)

ReactJS peut ainsi avoir une **représentation** de l’interface utilisateur avec son **état actuel** et l’**état après les changements** demandés par l’utilisateur. Très bien me diriez-vous, React a deux arbres en mémoire, mais comment fait-il pour mettre à jour le DOM? 

La réponse est simple, React va faire appel à l’étape de **Réconciliation**. Mais si, vous vous souvenez du mot qui ne vous parlait pas trop en introduction ! Je m’excuse d’avoir fait durer le suspense aussi longtemps alors sans plus tarder, Mesdames et Messieurs veuillez faire place à l’étape de **Réconciliation**.

<a name="reconciliation"></a>
# Réconciliation

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9k7ksdlpty8158ruavt3.jpg)

La **réconciliation** est l’étape qui consiste à détecter les changements de l’interface utilisateur et de les appliquer sur le DOM. Comme nous l’avons vu, React créé une **deuxième représentation** virtuel de l’interface après modification. Ce qu’il faut garder en tête c’est que le Virtual DOM n’est à aucun moment une représentation réelle et rien n’est affiché à l’écran. React a juste deux représentations en mémoire de l’état de l’interface. Il faut donc que React détecte de façon précise les éléments qui ont été impactés par les modifications. Pour cela, React utilise un **algorithme de comparaison**.

## L’algorithme de comparaison
Cet algorithme prend deux arbres (current tree et updating tree) et applique de façon récursive le traitement suivant sur les deux arbres :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6pgc5l5mqfnqg1nfjnh3.png)

Une fois que l’algorithme est passé sur tous les noeuds, React connaît les changements entre les deux représentations virtuelles du DOM.

## Application des changements dans le DOM

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/paa8cbl83fstyd55ebzd.jpg)

Après l’algorithme de comparaison, React possède une **liste de changement** à réaliser pour transformer le DOM. React utilise la librairie **React DOM** pour appliquer ces changements sur le DOM :link: [React Dom NPM](https://www.npmjs.com/package/react-dom). 

Avant la v16, l’étape de réconciliation utilisait le **Stack Reconcilier**. Le principe est simple, chacun des **changements d’état** est placé dans une **pile** les uns à la suite des autres. Une fois que la pile a fini d’être remplis, on vient appliquer les **actions** pour chaque changement en les dépilant. Ce procédé se fait de façon **synchrone** et pose de nombreux problèmes de performances et fluidités, détériorant ainsi l’expérience utilisateur.

Pour améliorer cela, lors de la v16, React a refacto ce système et à proposé la solution du **Fiber Algorithme**. 

Grâce au Fiber Algorithme, les changements à réaliser dans l’interface utilisateur ne sont plus fait de façon synchrone mais **asynchrone**. Chaque modification est vue comme une **unité de travail**, avec un état et une priorité. Toutes les unités de travail peuvent être **interrompues**, **reprises** ou encore **annulées**. React peut ainsi **prioriser** les changements importants et mettre en second plan ceux qui le sont moins.

Si vous voulez découvrir les profondeurs de l’algorithme Fiber, je vous suggère de lire les articles suivants :
:link: [An Introduction to React Fiber - The Algorithm Behind React](https://www.velotio.com/engineering-blog/react-fiber-algorithm)

:link: [Inside Fiber: in-depth overview of the new reconciliation algorithm in React](https://indepth.dev/posts/1008/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react)

<a name="conclusion"></a>
# Conclusion
Après la lecture de cet article, vous devriez avoir une meilleure vision du **Virtual DOM** ainsi que la **Réconciliation** qui sont deux concepts qui se cachent derrière React. Nous avons plongé dans les entrailles de la librairie afin d’en comprendre son fonctionnement. 

Ainsi, nous avons vu que le **Virtual DOM** n’est pas une fonctionnalité, mais bel et bien un outil sur lequel ReactJS s’appuie pour mettre en place sa **stratégie de mise à jour du DOM**. Le Virtual DOM permet de manipuler des objets et non le DOM directement. Ainsi, React peut optimiser le nombre d’action à réaliser dans le DOM. Couplées à l’étape de **Réconciliation**, nous obtenons une manière très efficace de faire beaucoup d’action dans l’interface utilisateur de façon optimale.

Nous avons également vu que le **Virtual DOM** est vital à React car c’est une librairie dite **State Driven UI**. ReactJS n’est pas plus rapide que le DOM, mais il est très bien optimisé pour une librairie de ce type, ce qui en fait toute sa renommée!

Grâce au Virtual DOM React nous offre la possibilité de nous concentrer sur ce qui compte vraiment, l’expérience utilisateur, au lieu de se concentrer sur des détails techniques tels que la mise à jour du DOM. 

Le secret de ReactJS, c’est de nous offre un doux mélange entre une **DX** de qualité et une **UX** optimisée.