I migliori strumenti di gestione dello stato di reazione per applicazioni aziendali

Pubblicato: 2022-03-11

Gli sviluppatori di applicazioni React a livello aziendale sanno quanto sia cruciale la gestione dello stato per un'esperienza utente finale coerente.

Tuttavia, l'utente non è l'unico interessato dalla gestione dello stato. Gli sviluppatori di React creano e mantengono lo stato. Vogliono che la gestione dello stato sia semplice, estensibile e atomica. React si è mossa in questa direzione introducendo hook.

Possono sorgere problemi quando lo stato dovrebbe essere condiviso tra molte componenti. Gli ingegneri devono trovare strumenti e librerie adatti alle loro esigenze, ma allo stesso tempo soddisfare gli elevati standard necessari per le app di livello aziendale.

In questo articolo analizzerò e confronterò le librerie più popolari e sceglierò quella più appropriata per la gestione dello stato in un'applicazione di livello aziendale.

Funzionalità di gestione dello stato di reazione integrate

React ha uno strumento eccellente per fornire dati su più componenti. L'obiettivo principale di Context è evitare il perforazione di prop. Il nostro obiettivo è quello di ottenere uno strumento di facile utilizzo per gestire lo stato in vari scenari che possono essere riscontrati nelle applicazioni aziendali: aggiornamenti frequenti, riprogettazioni, introduzione di nuove funzionalità e così via.

Sebbene tutto ciò sia teoricamente fattibile con Context, richiederebbe una soluzione personalizzata che richiede tempo per la configurazione, il supporto e l'ottimizzazione. L'unico vantaggio di Context è che non dipende da una libreria di terze parti, ma ciò non può superare lo sforzo di mantenere questo approccio.

Inoltre, Sebastian Markbage, membro del team di React, ha affermato che la nuova API Context non è stata creata e ottimizzata per gli aggiornamenti ad alta frequenza, ma piuttosto per gli aggiornamenti a bassa frequenza, come gli aggiornamenti dei temi e la gestione dell'autenticazione.

Esame delle biblioteche esistenti

Ci sono dozzine di strumenti di gestione dello stato su GitHub (ad esempio, Redux, MobX, Akita, Recoil e Zustand). Tuttavia, prendere in considerazione ciascuno di essi porterebbe a ricerche e confronti infiniti. Ecco perché ho ristretto la mia selezione ai tre principali concorrenti in base alla loro popolarità , utilizzo e manutentore .

Per rendere esplicito il confronto, utilizzerò i seguenti attributi di qualità:

  • Usabilità
  • Manutenibilità
  • Prestazione
  • Testabilità
  • Scalabilità (funziona con le stesse prestazioni sugli stati più grandi)
  • Modificabilità
  • Riutilizzabilità
  • Ecosistema (ha una varietà di strumenti di supporto per estendere la funzionalità)
  • Community (ha molti utenti e le loro domande trovano risposta sul web)
  • Portabilità (può essere utilizzata con librerie/framework diversi da React)

Redux

Redux è un contenitore di stato creato nel 2015. È diventato molto popolare perché:

  • Non c'era una seria alternativa quando è stato lanciato.
  • Ha fornito la separazione tra stato e azioni.
  • react-redux magic ha consentito una connessione di stato semplice.
  • Il co-creatore della libreria è Dan Abramov, acclamato sviluppatore di Facebook e membro del core team di React.

Animazione che mostra la progressione degli stati e delle azioni da e verso il riduttore, utilizzando Redux.

Hai un negozio globale in cui risiedono i tuoi dati. Ogni volta che devi aggiornare il negozio, invii un'azione che va al riduttore . A seconda del tipo di azione, il riduttore aggiorna lo stato in modo immutabile.

Per utilizzare Redux con React, dovrai sottoscrivere i componenti agli aggiornamenti del negozio tramite react-redux .

Esempio di API Redux

Le parti fondamentali di Redux nella base di codice che lo differenziano dagli altri strumenti sono le sezioni. Contengono tutta la logica delle azioni e dei riduttori.

CodeSandbox

 // slices/counter.js import { createSlice } from "@reduxjs/toolkit"; export const slice = createSlice({ name: "counter", initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; } } }); export const actions = slice.actions; export const reducer = slice.reducer; // store.js import { configureStore } from "@reduxjs/toolkit"; import { reducer as counterReducer } from "./slices/counter"; export default configureStore({ reducer: { counter: counterReducer } }); // index.js import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import App from './App' import store from './store' ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // App.js import React from "react"; import { useSelector, useDispatch } from "react-redux"; import { actions } from "./slices/counter"; const App = () => { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <div> <div> <button onClick={() => dispatch(actions.increment())}>Increment</button> <span>{count}</span> <button onClick={() => dispatch(actions.decrement())}>Decrement</button> </div> </div> ); }; export default App;

Attributi di qualità

  • Usabilità . Redux è diventato molto semplice con l'introduzione del pacchetto ufficiale del toolkit. Crei una sezione (una combinazione di stato iniziale, riduttori e azioni), la passi al negozio e accedi ad essa in un componente tramite hook.
  • Manutenibilità . Redux è semplice. Non richiede una profonda conoscenza per capire come migliorare o riparare qualcosa.
  • Prestazioni . L'influencer principale delle prestazioni con Redux è l'ingegnere del software. Redux è uno strumento semplice senza molta logica. Se vedi che gli aggiornamenti di stato sono lenti, puoi seguire le linee guida ufficiali per renderli più veloci.
  • Testabilità . Redux è costituito da funzioni pure (azioni e riduttori), che lo rendono ottimo per i test unitari. Fornisce inoltre il meccanismo per scrivere test di integrazione in cui l'archivio, le azioni e i riduttori lavorano insieme.
  • Scalabilità . Per impostazione predefinita, Redux ha uno stato globale, il che rende difficile la scalabilità. Tuttavia, esiste una libreria redux-dynamic-modules che consente la creazione di riduttori e middleware modulari.
  • Modificabilità . La personalizzazione di Redux è un affare semplice perché supporta il middleware.
  • Riutilizzabilità . Redux è indipendente dal framework, quindi è molto bravo nella riutilizzabilità.
  • Ecosistema . Redux offre un gigantesco ecosistema di utili componenti aggiuntivi, librerie e strumenti.
  • Comunità . Redux, la più antica libreria di gestione statale nel nostro confronto, ha accumulato una vasta comunità con una base di conoscenza significativa. Ci sono circa 30.000 (~19.000 risposte) domande con un tag redux su Stack Overflow.
  • Polso . Redux viene aggiornato e mantenuto regolarmente.

MobX

MobX è un'altra libreria relativamente vecchia con 23.000 stelle su GitHub. Ciò che lo distingue da Redux è che segue il paradigma OOP e utilizza osservabili. MobX è stato creato da Michel Weststrate ed è attualmente gestito da un gruppo di appassionati di open source con l'aiuto di Mendix, con sede a Boston.

Diagramma che illustra la gestione dello stato utilizzando MobX, dalle azioni, attraverso stati osservabili e valori calcolati, agli effetti collaterali.

In MobX, crei una classe JavaScript con una chiamata makeObservable all'interno del costruttore che è il tuo negozio osservabile (puoi usare @observable decorator se hai il caricatore appropriato). Quindi dichiari proprietà (stato) e metodi ( azioni e valori calcolati ) della classe. I componenti si iscrivono a questo archivio osservabile per accedere allo stato, ai valori calcolati e alle azioni.

Un'altra caratteristica essenziale di MobX è la mutabilità. Consente di aggiornare lo stato in modo silenzioso nel caso in cui si desideri evitare effetti collaterali.

Esempio di API MobX

Una caratteristica unica di MobX è che crei classi ES6 quasi pure con tutta la magia nascosta sotto il cofano. Richiede meno codice specifico della libreria per mantenere la concentrazione sulla logica.

CodeSandbox

 // stores/counter.js import { makeAutoObservable } from "mobx"; class CounterStore { value = 0; constructor() { makeAutoObservable(this); } increment() { this.value += 1; } decrement() { this.value -= 1; } } export default CounterStore; // index.js import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "mobx-react"; import App from "./App"; import CounterStore from "./stores/counter"; ReactDOM.render( <Provider counter={new CounterStore()}> <App /> </Provider>, document.getElementById("root") ); // App.js import React from "react"; import { inject, observer } from "mobx-react"; const App = inject((stores) => ({ counter: stores.counter }))( observer(({ counter }) => { return ( <div> <div> <button onClick={() => counter.increment()}>Increment</button> <span>{counter.value}</span> <button onClick={() => counter.decrement()}>Decrement</button> </div> </div> ); }) ); export default App;

Attributi di qualità

  • Usabilità . Un negozio osservabile è l'unico punto di ingresso per la gestione dello stato. Semplifica l'utilizzo di MobX perché hai l'unico posto da modificare.
  • Manutenibilità . È un aspetto negativo considerevole. Senza la conoscenza dell'API RxJS, non sarai in grado di ottenere il risultato desiderato. L'utilizzo di MobX in un team poco qualificato può portare a problemi di incoerenza dello stato.
  • Prestazioni . MobX è costituito da negozi indipendenti e ti consente di abbonarti agli unici di cui hai bisogno. È molto efficace.
  • Testabilità . Gli store osservabili sono semplici oggetti JavaScript con funzionalità reattive nascoste all'interno. Il test è lo stesso di qualsiasi altra classe JavaScript.
  • Scalabilità . I negozi osservabili sono suddivisi logicamente; non ci sono difficoltà nel ridimensionare MobX.
  • Modificabilità . MobX consente di creare osservabili personalizzati con comportamenti modificati. Inoltre, esiste un concetto chiamato reazioni. Le reazioni modellano gli effetti collaterali automatici. Queste cose rendono MobX molto personalizzabile.
  • Riutilizzabilità . MobX è agnostico rispetto ai framework, quindi è molto bravo nella riutilizzabilità.
  • Ecosistema . Ci sono centinaia di estensioni disponibili per MobX.
  • Comunità . MobX ha molti fan devoti. Ci sono ~1.600 (~1.000 risposte) domande con il tag mobx su Stack Overflow.
  • Polso . MobX viene aggiornato e mantenuto regolarmente.

Rinculo

Recoil è un relativamente nuovo arrivato, l'ultimo frutto del team React. L'idea di base è una semplice implementazione delle funzionalità React mancanti come lo stato condiviso e i dati derivati.

Ti starai chiedendo perché una libreria sperimentale viene rivista per progetti a livello aziendale. Innanzitutto, Recoil è uno degli argomenti più discussi nella community di React in questo momento. In secondo luogo, Recoil è supportato da Facebook e già utilizzato in alcune delle sue applicazioni, il che significa che ad un certo punto diventerà una versione stabile. Infine, è un approccio completamente nuovo per la condivisione dello stato in React e sono sicuro che anche se Recoil è deprecato, ci sarà un altro strumento che seguirà lo stesso percorso.

Recoil si basa su due termini: atom e selector . Un atomo è un pezzo di stato condiviso. Un componente può iscriversi a un atomo per ottenere/impostare il suo valore.

Diagramma raffigurante la gestione dello stato con Recoil, che mostra come i componenti possono iscriversi a un atomo per recuperarne o impostarne il valore.

Come puoi vedere nell'immagine, solo i componenti sottoscritti vengono renderizzati nuovamente quando il valore viene modificato. Rende Recoil molto performante.

Un'altra grande cosa che Recoil ha fuori dalla scatola è il selettore . Il selettore è un valore aggregato da un atomo o da un altro selettore. Per i consumatori, non c'è differenza tra atom e selector, devono solo iscriversi a una parte reattiva e utilizzarla.

Diagramma che illustra l'uso dei selettori in Recoil, la loro relazione con gli atomi e le modifiche causate da valori diversi.

Ogni volta che un atomo/selettore viene cambiato, i selettori che lo utilizzano (cioè sono iscritti ad esso) vengono rivalutati.

Esempio di API di rinculo

Il codice di Recoil è molto più diverso dai suoi concorrenti. Si basa sugli hook React e si concentra più sulla struttura dello stato che sulla mutazione di questo stato.

CodeSandbox

 // atoms/counter.js import { atom } from "recoil"; const counterAtom = atom({ key: "counter", default: 0 }); export default counterAtom; // index.js import React from "react"; import ReactDOM from "react-dom"; import { RecoilRoot } from "recoil"; import App from "./App"; ReactDOM.render( <RecoilRoot> <App /> </RecoilRoot>, document.getElementById("root") ); // App.js import React from "react"; import { useRecoilState } from "recoil"; import counterAtom from "./atoms/counter"; const App = () => { const [count, setCount] = useRecoilState(counterAtom); return ( <div> <div> <button onClick={() => setCount(count + 1)}>Increment</button> <span>{count}</span> <button onClick={() => setCount(count - 1)}>Decrement</button> </div> </div> ); }; export default App;

Attributi di qualità

  • Usabilità . Recoil è uno degli strumenti più facili da usare perché funziona come useState in React.
  • Manutenibilità . Tutto quello che devi fare in Recoil è mantenere selettori e ganci all'interno dei componenti: più valore, meno standard.
  • Prestazioni . Recoil costruisce un albero di stato al di fuori di React. L'albero dello stato ti consente di ottenere e ascoltare le cose di cui hai bisogno, non le modifiche dell'intero albero. È anche ben ottimizzato sotto il cofano.
  • Testabilità . Recoil fornisce un meccanismo per testare i suoi atomi e selettori.
  • Scalabilità . Uno stato che si divide in più parti indipendenti lo rende un buon giocatore in termini di scalabilità.
  • Modificabilità . Recoil è responsabile solo della memorizzazione dei valori e delle loro aggregazioni. Non ha flusso di dati, quindi può essere facilmente personalizzato.
  • Riutilizzabilità . Recoil si basa su React. Non può essere riutilizzato altrove.
  • Ecosistema . Al momento non esiste un ecosistema per Recoil.
  • Comunità . Recoil è troppo fresco per avere una grande comunità. Ci sono circa 70 domande con tag recoiljs su Stack Overflow.
  • Polso . Il rinculo viene aggiornato di rado (sei mesi trascorsi tra i suoi due aggiornamenti più recenti). Ha anche molti problemi aperti su GitHub.

Scelta del giusto strumento di gestione dello stato di reazione

Come si accumulano queste librerie di gestione dello stato globale di React quando si tratta di app di livello aziendale?

Recoil è giovane e fresco, ma al momento non ha comunità né ecosistema. Anche se Facebook ci sta lavorando e l'API sembra promettente, un'enorme applicazione React non può fare affidamento su una libreria con un debole supporto da parte della comunità. Inoltre, è sperimentale, il che lo rende ancora più pericoloso. Non è sicuramente una buona opzione per le applicazioni aziendali React oggi, ma vale la pena tenerla d'occhio.

MobX e Redux non condividono nessuno di questi problemi e la maggior parte dei grandi attori sul mercato li usa. Ciò che li rende diversi l'uno dall'altro è la curva di apprendimento. MobX richiede una conoscenza di base della programmazione reattiva. Se gli ingegneri coinvolti nel progetto non sono abbastanza esperti, l'applicazione potrebbe presentare incoerenze del codice, problemi di prestazioni e tempi di sviluppo più lunghi. MobX è accettabile e soddisferà le tue esigenze se il tuo team è a conoscenza della reattività.

Anche Redux presenta alcuni problemi, principalmente per quanto riguarda la scalabilità e le prestazioni. Tuttavia, a differenza di MobX, esistono soluzioni comprovate a questi problemi.

Tenendo conto di ogni vantaggio e svantaggio e considerando la mia esperienza personale, raccomando Redux come l'opzione migliore per le applicazioni React a livello aziendale.