Solid.js — Sous le capot d'un framework réactif

Feb 19 2023
Dans cet article, nous allons essayer de comprendre comment Solid.js est capable d'atteindre une réactivité de qualité.

Dans cet article, nous allons essayer de comprendre comment Solid.js est capable d'atteindre une réactivité de qualité.

Conditions préalables:

J'espère que quiconque lit cet article a une compréhension de base de React.js et connaît un peu Solid.js. Si vous n'avez pas encore consulté le site solid.js, je vous encourage à jeter un œil àhttps://www.solidjs.com/.

Performance js solide

Commençons par répondre à la question : qu'est-ce que la réactivité ?

La réactivité est la capacité d'une variable (tableau, chaîne, nombre, objet, etc.) à se mettre à jour lorsque sa valeur ou toute autre variable à laquelle elle fait référence est modifiée après la déclaration.

Aujourd'hui, le DOM que nous utilisons n'est pas réactif, ce qui signifie que si je fais référence à une variable JS en HTML et que cette variable change, le DOM ne sera pas automatiquement mis à jour avec cette variable.

React.js utilise Virtual DOM : créer des représentations DOM en termes d'objets, et chaque fois que l'état est mis à jour, vérifier la différence entre les objets et essayer de changer le DOM en quelques étapes minimales. React fonctionne de telle manière que chaque fois que l'état est mis à jour, il restitue tout ce composant.

On peut dire que réagir n'est pas vraiment de nature réactive. Cet article va plus en détail.

Solid.js utilise Signals : Le cœur d'un système réactif repose sur le modèle événement-émetteur. Je l'appelle le modèle " publication-abonné" . Voyons cela en termes de Solid.js
For Eg :

import { createSignal, createEffect } from "solid-js";

const [getCount, setCount] = createSignal(0);
// Here createSignal returns [getter, setter or publisher]

createEffect(() => console.log(getCount()));
// Here createEffect act as a subscriber to setCount event

// So whenever I'll do setCount it will log that count value 
// also it is triggered at first so you'll see 0 getting printed
setCount(getCount() + 1)

/**
Logs:
0
1
*/

C'est très bien, mais nous n'avons pas parlé de la façon dont cela fonctionne avec DOM ?
Vous pouvez imaginer qu'en arrière-plan, le DOM est également enveloppé automatiquement dans createEffect.
Alors quand tu vois

import { createSignal, createEffect } from "solid-js";

function App() {
  const [count, setCount] = useSignal(0);
  return <div>{count()}</div>
}

// It somehow gets converted into
function App() {
  const [count, setCount] = useSignal(0);
  return createEffect(() => <div>{count()}</div>)
}

J'ai écrit un morceau de code de base dans Solid; essayons de comprendre ce que fait Solid.js.

import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount(count() + 1);

  return (
    <>
    <button type="button" onClick={increment}>Click Me</button>
    <div>{count()}</div>
    </>
  );
}

render(() => <Counter />, document.getElementById("app")!);

import { template as _$template } from "solid-js/web";
import { delegateEvents as _$delegateEvents } from "solid-js/web";
import { createComponent as _$createComponent } from "solid-js/web";
import { insert as _$insert } from "solid-js/web";

/******* 
  1. If you see here the html got converted to string,
  Here the template function converts the string to actual HTML DOM
  
  function template(HTML) {
    const dom = document.createElement('template');
    dom.innerHTML = HTML;
    return dom.firstChild;
  }
*****/
const _tmpl$ = /*#__PURE__*/_$template(`<button type="button">Click Me</button>`, 2),
  _tmpl$2 = /*#__PURE__*/_$template(`<div></div>`, 2);

import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount(count() + 1);

  return [(() => {
    const _el$ = _tmpl$.cloneNode(true);
    _el$.$$click = increment;
    return _el$;
  })(), (() => {
    const _el$2 = _tmpl$2.cloneNode(true);

    /******* 
      2. Here insert functions internally uses createEffect and 
         make DOM changes whenever increment function is called.
      
        function insert(parentElement, value) {
          createEffect(() => parentElement.innerHTML = value);
        }
    *****/

    _$insert(_el$2, count);
    return _el$2;
  })()];
}
render(() => _$createComponent(Counter, {}), document.getElementById("app"));
_$delegateEvents(["click"]);

C'est ma compréhension du fonctionnement de solid.js en arrière-plan, et j'aimerais entendre des commentaires si je me suis trompé quelque part.

Ressources:

Parler de réactivité —https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p
https://www.youtube.com/watch?v=UhGV8yYnvQE

expression-dom —https://www.youtube.com/watch?v=jnZmG4hyNas