Cele mai bune instrumente de management de stat React pentru aplicații de întreprindere

Publicat: 2022-03-11

Dezvoltatorii de aplicații React la nivel de întreprindere știu cât de crucial este managementul de stat pentru o experiență coerentă a utilizatorului final.

Cu toate acestea, utilizatorul nu este singurul afectat de managementul statului. Dezvoltatorii React creează și mențin starea. Ei doresc ca managementul de stat să fie simplu, extensibil și atomic. React s-a mutat în această direcție prin introducerea cârligelor.

Pot apărea probleme atunci când statul ar trebui împărțit între mai multe componente. Inginerii trebuie să găsească instrumente și biblioteci care se potrivesc nevoilor lor, dar în același timp să îndeplinească standardele înalte necesare pentru aplicațiile de nivel enterprise.

În acest articol, voi analiza și compara cele mai populare biblioteci și o voi alege pe cea mai potrivită pentru managementul de stat într-o aplicație la nivel de întreprindere.

Capacități de gestionare a stării React încorporate

React are un instrument excelent pentru furnizarea de date pe mai multe componente. Scopul principal al Context este acela de a evita forarea cu prop. Scopul nostru este să obținem un instrument ușor de utilizat pentru a gestiona starea în diverse scenarii care pot fi întâlnite în aplicațiile de întreprindere: actualizări frecvente, reproiectări, introducerea de noi funcții și așa mai departe.

Deși toate acestea sunt realizabile teoretic cu Context, ar necesita o soluție personalizată care necesită timp pentru a se configura, a susține și a optimiza. Singurul avantaj al Context este că nu depinde de o bibliotecă terță parte, dar asta nu poate depăși efortul de a menține această abordare.

În plus, Sebastian Markbage, membru al echipei React, a menționat că noul Context API nu a fost construit și optimizat pentru actualizări de înaltă frecvență, ci mai degrabă pentru actualizări de joasă frecvență, cum ar fi actualizările temei și gestionarea autentificărilor.

Examinarea bibliotecilor existente

Există zeci de instrumente de management de stat pe GitHub (de exemplu, Redux, MobX, Akita, Recoil și Zustand). Cu toate acestea, luarea în considerare a fiecăruia dintre ele ar duce la cercetări și comparații nesfârșite. De aceea mi-am restrâns selecția la cei trei concurenți principali în funcție de popularitate , utilizare și întreținere .

Pentru a face comparația explicită, voi folosi următoarele atribute de calitate:

  • Utilizabilitate
  • Mentenabilitatea
  • Performanţă
  • Testabilitate
  • Scalabilitate (funcționează cu aceeași performanță pe stările mai mari)
  • Modificabilitate
  • Reutilizabilitate
  • Ecosistem (are o varietate de instrumente de ajutor pentru a extinde funcționalitatea)
  • Comunitate (are mulți utilizatori și întrebările lor primesc răspuns pe web)
  • Portabilitate (poate fi utilizat cu biblioteci/cadre altele decât React)

Redux

Redux este un container de stat creat în 2015. A devenit extrem de popular deoarece:

  • Nu a existat nicio alternativă serioasă la lansare.
  • A asigurat separarea între stat și acțiuni.
  • react-redux magic a activat o conexiune de stare simplă.
  • Co-creatorul bibliotecii este apreciatul dezvoltator Facebook și membru al echipei React, Dan Abramov.

Animație care arată progresul stărilor și acțiunilor de la și către reductor, folosind Redux.

Aveți un magazin global unde se află datele dvs. Ori de câte ori trebuie să actualizați magazinul, trimiteți o acțiune care merge către reductor . În funcție de tipul de acțiune, reductorul actualizează starea într-un mod imuabil.

Pentru a utiliza Redux cu React, va trebui să vă abonați componentele la actualizările magazinului prin react-redux .

Exemplu API Redux

Părțile fundamentale ale Redux din baza de cod care îl diferențiază de celelalte instrumente sunt feliile. Ele conțin toată logica acțiunilor și reductorilor.

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;

Atribute de calitate

  • Utilizabilitate . Redux a devenit foarte simplu odată cu introducerea pachetului oficial de instrumente. Creați o felie (o combinație a stării inițiale, reductoare și acțiuni), o transmiteți magazinului și o accesați într-o componentă prin cârlige.
  • Mentenabilitatea . Redux este simplu. Nu necesită cunoștințe profunde pentru a înțelege cum să îmbunătățiți sau să reparați ceva.
  • Performanță . Principalul factor de influență a performanței cu Redux este inginerul software. Redux este un instrument simplu, fără prea multă logică. Dacă observați că actualizările de stat sunt lente, puteți urma instrucțiunile oficiale pentru a le face mai rapide.
  • Testabilitate . Redux constă din funcții pure (acțiuni și reductoare), ceea ce îl face excelent pentru testarea unitară. De asemenea, oferă mecanismul pentru a scrie teste de integrare în care magazinul, acțiunile și reductoarele lucrează împreună.
  • Scalabilitate . În mod implicit, Redux are o singură stare globală, ceea ce face dificilă scalarea. Cu toate acestea, există o bibliotecă redux-dynamic-module care permite crearea de reductoare modulare și middleware.
  • Modificabilitate . Personalizarea Redux este o afacere fără efort, deoarece acceptă middleware.
  • Reutilizabilitate . Redux este agnostic de cadru, deci este foarte bun la reutilizare.
  • Ecosistem . Redux oferă un ecosistem uriaș de suplimente, biblioteci și instrumente utile.
  • Comunitatea . Redux, cea mai veche bibliotecă de management de stat din comparația noastră, a adunat o comunitate mare cu o bază de cunoștințe semnificativă. Există ~ 30.000 (~ 19.000 de întrebări cu răspunsuri) cu o etichetă redux pe Stack Overflow.
  • Puls . Redux este actualizat și întreținut în mod regulat.

MobX

MobX este o altă bibliotecă relativ veche cu 23.000 de stele pe GitHub. Ceea ce îl diferențiază de Redux este că urmează paradigma OOP și utilizează observabile. MobX a fost creat de Michel Weststrate și este întreținut în prezent de un grup de entuziaști open-source cu ajutorul lui Mendix din Boston.

Diagramă care ilustrează gestionarea stării folosind MobX, de la acțiuni, prin stări observabile și valori calculate, până la efecte secundare.

În MobX, creați o clasă JavaScript cu un apel makeObservable în interiorul constructorului care este magazinul dvs. observabil (puteți folosi @observable decorator dacă aveți încărcătorul corespunzător). Apoi declarați proprietățile (starea) și metodele ( acțiunile și valorile calculate ) ale clasei. Componentele se abonează la acest magazin observabil pentru a accesa starea, valorile calculate și acțiunile.

O altă caracteristică esențială a MobX este mutabilitatea. Permite actualizarea stării în tăcere în cazul în care doriți să evitați efectele secundare.

Exemplu API MobX

O caracteristică unică a MobX este că creați clase ES6 aproape pure, cu toată magia ascunsă sub capotă. Este nevoie de mai puțin cod specific bibliotecii pentru a menține concentrarea asupra logicii.

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;

Atribute de calitate

  • Utilizabilitate . Un magazin observabil este punctul unic de intrare pentru managementul statului. Face utilizarea MobX simplă, deoarece aveți singurul loc de modificat.
  • Mentenabilitatea . Este un dezavantaj considerabil. Fără cunoștințe despre RxJS API, nu veți putea obține rezultatul dorit. Utilizarea MobX într-o echipă slab calificată poate duce la probleme de inconsecvență a stării.
  • Performanță . MobX este format din magazine independente și vă permite să vă abonați la singurele de care aveți nevoie. Este foarte eficient.
  • Testabilitate . Magazinele observabile sunt obiecte JavaScript simple cu funcționalitate reactivă ascunsă în interior. Testarea este aceeași ca pentru orice altă clasă JavaScript.
  • Scalabilitate . Magazinele observabile sunt împărțite logic; nu există nicio dificultate în scalarea MobX.
  • Modificabilitate . MobX permite crearea de observabile personalizate cu comportamente modificate. În plus, există un concept numit reacții. Reacțiile modelează efecte secundare automate. Aceste lucruri fac MobX foarte personalizabil.
  • Reutilizabilitate . MobX este agnostic de cadre, deci este foarte bun la reutilizare.
  • Ecosistem . Există sute de extensii disponibile pentru MobX.
  • Comunitatea . MobX are o mulțime de fani devotați. Există ~ 1.600 (~ 1.000 de întrebări cu răspunsuri) cu eticheta mobx pe Stack Overflow.
  • Puls . MobX este actualizat și întreținut în mod regulat.

Recul

Recoil este un relativ nou venit, cea mai recentă creație a echipei React. Ideea de bază din spatele acesteia este o implementare simplă a caracteristicilor React lipsă, cum ar fi starea partajată și datele derivate.

S-ar putea să vă întrebați de ce o bibliotecă experimentală este revizuită pentru proiecte la nivel de întreprindere. În primul rând, Recoil este unul dintre cele mai discutate subiecte în comunitatea React în acest moment. În al doilea rând, Recoil este susținut de Facebook și deja folosit în unele dintre aplicațiile sale, ceea ce înseamnă că va deveni o versiune stabilă la un moment dat. În cele din urmă, este o abordare complet nouă pentru partajarea stării în React și sunt sigur că, chiar dacă Recoil este depreciat, va exista un alt instrument care urmează aceeași cale.

Recul este construit pe baza a doi termeni: atom și selector . Un atom este o piesă cu stare partajată. O componentă se poate abona la un atom pentru a obține/seta valoarea acestuia.

Diagramă care ilustrează gestionarea stării cu Recoil, care arată modul în care componentele se pot abona la un atom pentru a-i prelua sau a seta valoarea.

După cum puteți vedea în imagine, numai componentele abonate sunt re-redate atunci când valoarea este schimbată. Face ca Recoil să fie foarte performant.

Un alt lucru grozav pe care Recoil îl are din cutie este selectorul . Selectorul este o valoare agregată dintr-un atom sau alt selector. Pentru consumatori, nu există nicio diferență între atom și selector, trebuie doar să se aboneze la o parte reactivă și să o folosească.

Diagrama care ilustrează utilizarea selectoarelor în Recul, relația acestora cu atomii și modificările cauzate de diferite valori.

Ori de câte ori un atom/selector este schimbat, selectorii care îl folosesc (adică sunt abonați la el) sunt reevaluați.

Exemplu API Recoil

Codul lui Recoil este mult mai diferit de concurenții săi. Se bazează pe cârlige React și se concentrează mai mult pe structura statului decât pe mutarea acestei stări.

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;

Atribute de calitate

  • Utilizabilitate . Recoil este unul dintre cele mai ușor de utilizat, deoarece funcționează ca useState în React.
  • Mentenabilitatea . Tot ce trebuie să faceți în Recoil este să mențineți selectoarele și cârligele în interiorul componentelor - mai multă valoare, mai puțină placă.
  • Performanță . Recoil construiește un arbore de stare în afara lui React. Arborele de stare vă permite să obțineți și să ascultați lucrurile de care aveți nevoie, nu modificările întregului arbore. De asemenea, este bine optimizat sub capotă.
  • Testabilitate . Recul oferă un mecanism pentru testarea atomilor și selectoarelor sale.
  • Scalabilitate . O stare care se împarte în mai multe piese independente îl face un bun jucător în scalabilitate.
  • Modificabilitate . Recoil este responsabil doar pentru stocarea valorilor și agregarea acestora. Nu are flux de date, astfel încât poate fi personalizat cu ușurință.
  • Reutilizabilitate . Recul se bazează pe React. Nu poate fi refolosit în altă parte.
  • Ecosistem . Nu există un ecosistem pentru Recoil în acest moment.
  • Comunitatea . Recul este prea proaspăt pentru a avea o comunitate mare. Există ~ 70 de întrebări cu eticheta recoiljs pe Stack Overflow.
  • Puls . Recul este actualizat rar (șase luni au trecut între cele mai recente două actualizări). De asemenea, are o mulțime de probleme deschise pe GitHub.

Alegerea instrumentului de management al stării React potrivit

Cum se comportă aceste biblioteci globale React de management de stat când vine vorba de aplicații de nivel enterprise?

Recul este tânăr și proaspăt, dar nu are comunitate și nici ecosistem în acest moment. Chiar dacă Facebook lucrează la asta și API-ul pare promițător, o aplicație React uriașă nu se poate baza pe o bibliotecă cu suport slab comunitar. În plus, este experimental, ceea ce îl face și mai periculos. Cu siguranță nu este o opțiune bună pentru aplicațiile de întreprindere React astăzi, dar merită să fii cu ochii pe ea.

MobX și Redux nu împărtășesc niciuna dintre aceste probleme și majoritatea jucătorilor mari de pe piață le folosesc. Ceea ce îi face diferiți unul de celălalt este curba de învățare. MobX necesită o înțelegere de bază a programării reactive. Dacă inginerii implicați în proiect nu sunt suficient de calificați, aplicația poate avea inconsecvențe de cod, probleme de performanță și timp de dezvoltare crescut. MobX este acceptabil și vă va satisface nevoile dacă echipa dumneavoastră este conștientă de reactivitate.

Redux are și unele probleme, mai ales legate de scalabilitate și performanță. Cu toate acestea, spre deosebire de MobX, există soluții dovedite la aceste probleme.

Luând în considerare fiecare avantaj și dezavantaj și ținând cont de experiența mea personală, recomand Redux ca cea mai bună opțiune pentru aplicațiile React la nivel de întreprindere.