Jetez un œil à la façon dont certaines des bibliothèques JavaScript les plus populaires gèrent l’état, avec ou sans signaux, et décidez si c’est une fonctionnalité que vous rechercherez à l’avenir.
Il semble que la plupart des frameworks utilisent désormais des signaux pour gérer l’état réactif. Nous les avons d’abord vus dans SolidJS et Vue, puis Preact et Qwik, et maintenant Angular. Nous n’avons pas toujours besoin de signaux, mais ils peuvent faciliter les choses. Voyons comment l’état est géré dans chaque framework.
Aucun signal
Réagir
import { useState } from "react";
export default function App() {
const [x, setX] = useState(1);
const x2 = x * 2;
return (
<>
<p>{x2}</p>
<button onClick={() => setX(x + 1)}>Double</button>
</>
);
}
Voir le CodeSandbox.
React a utilisé useState
depuis 2018. Cela a considérablement réduit la complexité des composants de classe. Bien que cela fonctionne très bien, chaque composant enfant sera restitué à moins que vous mémoriser le composant avec useMemo
ou useCallback
, ce qui pourrait entraîner un rendu plus complexe. Certaines personnes résolvent ce problème en important directement @preact/signals-react
dans leur projet de réaction. useState
peut également prendre en charge des valeurs réactives profondes si vous réinitialisez l’objet entier.
RXJS
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BehaviorSubject, map } from 'rxjs';
@Component({
selector: 'app-rxjs',
standalone: true,
imports: [CommonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<p>{{ x1 | async }}</p>
<button (click)="increment()">Double</button>
`
})
export class RxjsComponent {
readonly x = new BehaviorSubject(1);
readonly x1 = this.x.pipe(map((v) => v * 2));
increment() {
this.x.next(this.x.value + 1);
}
}
Voir le StackBlitz angulaire.
Angular avant les signaux repose fortement sur RXJS. Bien que RXJS résout à peu près le problème (même sans ZoneJS), cela peut être une bête et difficile à comprendre si vous n’êtes pas sur le point de le maîtriser.
Vous devez vous abonner à des observables ou à des sujets, et, même avec des canaux de programmation déclaratifs, combineLatest
peut avoir des effets secondaires pour les valeurs mises à jour, y compris le réactif problème de diamant.
Dans l’ensemble, ce sont des problèmes non viables si vous maîtrisez RXJS, car en fin de compte, RXJS est conçu pour la complexité et non pour la simplicité. RXJS peut prendre en charge tout type d’objet si vous utilisez les bons opérateurs. Puissant, mais pas simple.
Svelte
<script>
import { writable, derived } from 'svelte/store';
const x = writable(1);
const x1 = derived(x, $x => $x * 2);
</script>
<p>{$x1}</p>
<button on:click={() => x.update(v => ++v)}>Double</button>
Voir le REPL svelte.
Svelte n’a pas besoin de signaux, car l’idée de ses magasins inscriptibles est en grande partie copiée de RXJS et simplifiée. En fait, si vous devez gérer des données asynchrones avec conditions de course, les magasins Svelte sont interopérables avec RXJS. Comme Signals, les magasins Svelte ciblent simplement la partie nécessaire de l’interface utilisateur qui doit être mise à jour. Vous devez remplacer l’objet entier pour des mises à jour réactives approfondies, mais cela peut être facilement fait avec update
. La magie du compilateur est incroyable.
Signaux
Vue
<script setup>
import { ref, computed } from 'vue'
const x = ref(1)
const x1 = computed(() => x.value * 2)
</script>
<template>
<p>{{ x1 }}</p>
<button @click="x++">Double</button>
</template>
Voir le Aire de jeux Vue.
Dans Vue, les signaux sont simplement ref
. Depuis le reactive
store ne gère pas les valeurs calculées immédiatement, Vue a ref
. Vue gère par défaut une réactivité profonde avec les objets et possède également le reactive
fonction. Les signaux améliorent simplement Vue.
Rapide
import { component$, useSignal, useComputed$ } from '@builder.io/qwik';
export default component$(() => {
const x = useSignal(1);
const x1 = useComputed$(() => 2 * x.value);
return <>
<p>{x1}</p>
<button onClick$={() => x.value++}>Double</button>
</>;
});
Voir le Aire de jeux Qwik.
Qwik vient de voir ce qui fonctionnait bien avec Svelte et Vue et a décidé d’avoir des signaux qui fonctionnent comme prévu. Vous pouvez obtenir des objets imbriqués réactifs avec useStore
au lieu de useSignal
. Bien entendu, Qwik sérialise automatiquement les valeurs du serveur vers le navigateur, ce qu’aucun autre framework ne fait. Avec Signaux et Resumability, Qwik remporte à peu près le concours UX.
SolidJS
import { render } from "solid-js/web";
import { createSignal } from "solid-js";
function Counter() {
const [x, setX] = createSignal(1);
const x1 = () => x() * 2;
return <>
<p>{x1()}</p>
<button type="button" onClick={() => setX(x() + 1)}>Double</button>
</>;
}
render(() => <Counter />, document.getElementById("app")!);
Voir le Terrain de jeu SolidJS.
Solid utilise une approche intéressante en appelant les signaux en fonction. Cela garantit que les valeurs sont réactives aux moments appropriés. Ils sont également déstructurés comme ceux de React useState
, puisque SolidJS est censé être le framework JS le plus rapide du marché, fortement inspiré de React. Preact ne pourrait jamais être aussi rapide, bien qu’il conserve la compatibilité de la bibliothèque React. SolidJS prend également en charge les valeurs réactives imbriquées avec createStore
. Solid est peut-être le framework JavaScript pur le plus rapide du marché, les signaux étant une raison.
Préagir
import { render } from 'preact';
import { signal, computed } from "@preact/signals@1.1.0";
const x = signal(1);
const x1 = computed(() => x.value * 2);
function Counter() {
return <>
<p>{x1}</p>
<button onClick={() => x.value++}>Double</button>
</>;
}
render(<Counter />, document.getElementById('app'));
Voir le Préagir REPL.
Preact a résolu le problème avant React en créant sa propre version des signaux. Fortement inspirés de Vue et SolidJS, ses signaux sont extrêmement simples à utiliser. Vous obtenez une réactivité imbriquée en renvoyant l’intégralité de l’objet modifié. Je pense avoir entendu plus de personnes utiliser la bibliothèque de signaux Preact dans React que d’utilisateurs Preact ?
Angulaire
import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<p>{{ x2() }}</p>
<button (click)="increment()">Double</button>
`
})
export class AppComponent {
readonly x = signal(1);
readonly x2 = computed(() => this.x() * 2);
increment() {
this.x.update((x) => ++x);
}
}
Voir le StackBlitz angulaire.
Enfin, nous avons des signaux angulaires. Ils semblent simples comme les signaux Preact, mais utilisent également l’approche fonctionnelle comme SolidJS. De plus, vous pouvez effectuer des conversions aller-retour en observable avec fromObservable
et fromSignal
.
Au lieu de vérifier l’intégralité de l’arborescence des composants pour détecter les modifications, ils mettront à jour uniquement ce qui a été modifié. Bien qu’ils ne gèrent pas les données asynchrones (nous avons RXJS pour cela), ils augmentent les performances et diminuent la complexité.
Bientôt, nous verrons la possibilité de supprimer définitivement ZoneJS d’Angular. Vous ne pouvez pas parler de réactivité angulaire sans vérifier Chaîne de Joshua Morony.
Bien que Svelte n’en ait pas besoin, les signaux sont l’avenir de chaque framework, à l’exception du plus grand. React recevra-t-il un jour des signaux ? Aucune idée. Le mot clé pour Signaux est « granularité ». Vous mettez à jour uniquement ce qui a changé. Personnellement, j’utiliserai un framework avec Signals à l’avenir.
Source link