Redux · Un'introduzione
Pubblicato: 2022-03-10Redux è una delle librerie più importanti nello sviluppo front-end di questi tempi. Tuttavia, molte persone sono confuse su cosa sia e quali siano i suoi vantaggi.
Come afferma la documentazione, Redux è un contenitore di stato prevedibile per le app JavaScript. Per riformularlo, è un'architettura del flusso di dati dell'applicazione, piuttosto che una libreria tradizionale o un framework come Underscore.js e AngularJS.
Ulteriori letture su SmashingMag
- Perché dovresti considerare React Native per la tua app mobile
- Automazione dei test per app, giochi e Web mobile
- Rendering lato server con React, Node ed Express
- Note sull'accessibilità resa dal client
Redux è stato creato da Dan Abramov intorno a giugno 2015. È stato ispirato da Flux di Facebook e dal linguaggio di programmazione funzionale Elm. Redux è diventato popolare molto rapidamente grazie alla sua semplicità , alle dimensioni ridotte (solo 2 KB) e all'ottima documentazione. Se vuoi imparare come funziona Redux internamente e approfondire la libreria, considera di dare un'occhiata al corso gratuito di Dan.
Redux viene utilizzato principalmente per la gestione dello stato dell'applicazione. Per riassumere, Redux mantiene lo stato di un'intera applicazione in un singolo albero di stato immutabile (oggetto), che non può essere modificato direttamente. Quando qualcosa cambia, viene creato un nuovo oggetto (usando azioni e riduttori). Esamineremo i concetti fondamentali in dettaglio di seguito.
In che cosa differisce da MVC e Flux?
Per dare un po' di prospettiva, prendiamo il classico pattern model-view-controller (MVC), poiché la maggior parte degli sviluppatori lo conosce. Nell'architettura MVC esiste una netta separazione tra dati (modello), presentazione (vista) e logica (controllore). C'è un problema con questo, specialmente nelle applicazioni su larga scala: il flusso di dati è bidirezionale. Ciò significa che una modifica (un input dell'utente o una risposta API) può influire sullo stato di un'applicazione in molti punti del codice, ad esempio l'associazione dati a due vie. Può essere difficile da mantenere ed eseguire il debug.
Il flusso è molto simile a Redux. La differenza principale è che Flux ha più archivi che modificano lo stato dell'applicazione e trasmette queste modifiche come eventi. I componenti possono iscriversi a questi eventi per sincronizzarsi con lo stato corrente. Redux non ha un dispatcher , che in Flux viene utilizzato per trasmettere i payload ai callback registrati. Un'altra differenza in Flux è che sono disponibili molte varietà e ciò crea confusione e incoerenza.
Vantaggi di Redux
Potresti chiederti "Perché dovrei usare Redux?" Ottima domanda. Ci sono alcuni vantaggi nell'usare Redux nella tua prossima applicazione:
- Prevedibilità del risultato
C'è sempre una fonte di verità, il negozio, senza confusione su come sincronizzare lo stato corrente con le azioni e altre parti dell'applicazione. - Manutenibilità
Avere un risultato prevedibile e una struttura rigida semplificano la manutenzione del codice. - Organizzazione
Redux è più rigoroso su come organizzare il codice, il che rende il codice più coerente e più facile con cui lavorare per un team. - Rendering del server
Questo è molto utile, soprattutto per il rendering iniziale, per una migliore esperienza utente o per l'ottimizzazione dei motori di ricerca. Basta passare lo store creato sul server al lato client. - Strumenti di sviluppo
Gli sviluppatori possono tenere traccia di tutto ciò che accade nell'app in tempo reale, dalle azioni ai cambiamenti di stato. - Comunità ed ecosistema
Questo è un enorme vantaggio ogni volta che stai imparando o utilizzando qualsiasi libreria o framework. Avere una community dietro Redux lo rende ancora più interessante da usare. - Facilità di test
La prima regola per scrivere codice verificabile è scrivere piccole funzioni che fanno solo una cosa e che sono indipendenti. Il codice di Redux è composto principalmente da funzioni che sono proprio questo: piccole, pure e isolate.
Programmazione Funzionale
Come accennato, Redux è stato costruito sulla base di concetti di programmazione funzionale. Comprendere questi concetti è molto importante per capire come e perché Redux funziona in quel modo. Esaminiamo i concetti fondamentali della programmazione funzionale:
- È in grado di trattare le funzioni come oggetti di prima classe.
- È in grado di passare funzioni come argomenti.
- È in grado di controllare il flusso utilizzando funzioni, ricorsioni e array.
- È in grado di utilizzare funzioni pure, ricorsive, di ordine superiore, di chiusura e anonime.
- È in grado di utilizzare funzioni di supporto, come mappa, filtro e riduzione.
- È in grado di concatenare le funzioni.
- Lo stato non cambia (cioè è immutabile).
- L'ordine di esecuzione del codice non è importante.
La programmazione funzionale ci consente di scrivere un codice più pulito e modulare. Scrivendo funzioni più piccole e più semplici che sono isolate nell'ambito e nella logica, possiamo rendere il codice molto più semplice da testare, mantenere ed eseguire il debug. Ora queste funzioni più piccole diventano codice riutilizzabile e ciò ti consente di scrivere meno codice e meno codice è una buona cosa. Le funzioni possono essere copiate e incollate ovunque senza alcuna modifica. Le funzioni che sono isolate nell'ambito e che eseguono solo un'attività dipenderanno meno dagli altri moduli in un'app e questo accoppiamento ridotto è un altro vantaggio della programmazione funzionale.

Vedrai funzioni pure, funzioni anonime, chiusure, funzioni di ordine superiore e catene di metodi, tra le altre cose, molto spesso quando lavori con JavaScript funzionale. Redux utilizza pesantemente le funzioni pure, quindi è importante capire cosa sono.
Le funzioni pure restituiscono un nuovo valore in base agli argomenti loro passati. Non modificano gli oggetti esistenti; invece, ne restituiscono uno nuovo. Queste funzioni non si basano sullo stato da cui vengono chiamate e restituiscono solo lo stesso risultato per qualsiasi argomento fornito. Per questo motivo sono molto prevedibili.
Poiché le funzioni pure non modificano alcun valore, non hanno alcun impatto sull'ambito o su eventuali effetti collaterali osservabili e ciò significa che uno sviluppatore può concentrarsi solo sui valori restituiti dalla funzione pura.
Dove può essere utilizzato Redux?
La maggior parte degli sviluppatori associa Redux a React, ma può essere utilizzato con qualsiasi altra libreria di viste. Ad esempio, puoi utilizzare Redux con AngularJS, Vue.js, Polymer, Ember, Backbone.js e Meteor. Redux più React, tuttavia, è ancora la combinazione più comune. Assicurati di imparare React nell'ordine giusto: la guida migliore è quella di Pete Hunt, che è molto utile per gli sviluppatori che stanno iniziando con React e sono sopraffatti da tutto ciò che accade nell'ecosistema. L'affaticamento da JavaScript è una preoccupazione legittima tra gli sviluppatori front-end, sia nuovi che esperti, quindi prenditi il tempo necessario per imparare React o Redux nel modo giusto nell'ordine giusto.
Uno dei motivi per cui Redux è fantastico è il suo ecosistema. Sono disponibili così tanti articoli, tutorial, middleware, strumenti e boilerplate. Personalmente, utilizzo il boilerplate di David Zukowski perché ha tutto ciò che serve per creare un'applicazione JavaScript, con React, Redux e React Router. Una parola di cautela: cerca di non utilizzare boilerplate e kit di base quando apprendi nuovi framework come React e Redux. Lo renderà ancora più confuso, perché non capirai come funziona tutto insieme. Imparalo prima e crea un'app molto semplice, idealmente come progetto collaterale, quindi usa le piastre standard per le app di produzione per risparmiare tempo.
Parti di costruzione di Redux
I concetti di Redux possono sembrare complicati o fantasiosi, ma sono semplici. Ricorda che la libreria è di soli 2 KB. Redux ha tre parti di costruzione: azioni, negozio e riduttori.

Discutiamo di ciò che ciascuno fa.

Azioni
In poche parole, le azioni sono eventi. Le azioni inviano i dati dall'applicazione (interazioni utente, eventi interni come chiamate API e invii di moduli) all'archivio. Il negozio riceve informazioni solo dalle azioni. Le azioni interne sono semplici oggetti JavaScript che hanno una proprietà di type
(solitamente costante), che descrive il tipo di azione e il carico utile delle informazioni inviate al negozio.
{ type: LOGIN_FORM_SUBMIT, payload: {username: 'alex', password: '123456'} }
Le azioni vengono create con i creatori di azioni. Sembra ovvio, lo so. Sono solo funzioni che restituiscono azioni.
function authUser(form) { return { type: LOGIN_FORM_SUBMIT, payload: form } }
Chiamare azioni in qualsiasi punto dell'app, quindi, è molto semplice. Usa il metodo di dispatch
, in questo modo:
dispatch(authUser(form));
Riduttori
Abbiamo già discusso di cos'è un riduttore in JavaScript funzionale. Si basa sul metodo di riduzione dell'array, in cui accetta un callback (riduttore) e consente di ottenere un singolo valore da più valori, somme di numeri interi o un accumulo di flussi di valori. In Redux, i riduttori sono funzioni (pure) che prendono lo stato corrente dell'applicazione e un'azione e quindi restituiscono un nuovo stato. Capire come funzionano i riduttori è importante perché svolgono la maggior parte del lavoro. Ecco un riduttore molto semplice che prende lo stato corrente e un'azione come argomenti e quindi restituisce lo stato successivo:
function handleAuth(state, action) { return _.assign({}, state, { auth: action.payload }); }
Per app più complesse, è possibile utilizzare l'utilità combineReducers()
fornita da Redux (anzi, consigliata). Combina tutti i riduttori nell'app in un unico riduttore di indice. Ogni riduttore è responsabile della propria parte dello stato dell'app e il parametro dello stato è diverso per ogni riduttore. L'utilità combineReducers()
rende la struttura del file molto più semplice da mantenere.
Se un oggetto (stato) cambia solo alcuni valori, Redux crea un nuovo oggetto, i valori che non sono stati modificati si riferiranno al vecchio oggetto e verranno creati solo i nuovi valori. È fantastico per le prestazioni. Per renderlo ancora più efficiente puoi aggiungere Immutable.js.
const rootReducer = combineReducers({ handleAuth: handleAuth, editProfile: editProfile, changePassword: changePassword });
Negozio
Store è l'oggetto che contiene lo stato dell'applicazione e fornisce alcuni metodi di supporto per accedere allo stato, inviare azioni e registrare listener. L'intero stato è rappresentato da un unico negozio. Qualsiasi azione restituisce un nuovo stato tramite riduttori. Ciò rende Redux molto semplice e prevedibile.
import { createStore } from 'redux'; let store = createStore(rootReducer); let authInfo = {username: 'alex', password: '123456'}; store.dispatch(authUser(authInfo));
Strumenti per sviluppatori, viaggi nel tempo e ricarica a caldo
Per rendere più facile lavorare con Redux, specialmente quando si lavora con un'applicazione su larga scala, consiglio di usare Redux DevTools. È incredibilmente utile, mostrando i cambiamenti dello stato nel tempo, i cambiamenti in tempo reale, le azioni e lo stato attuale. Ciò consente di risparmiare tempo e fatica evitando lo stato e le azioni correnti di console.log

Redux ha un'implementazione leggermente diversa del viaggio nel tempo rispetto a Flux. In Redux, puoi tornare a uno stato precedente e persino portare il tuo stato in una direzione diversa da quel momento in poi. Redux DevTools supporta le seguenti funzionalità di "viaggio nel tempo" nel flusso di lavoro Redux (pensa a loro come comandi Git per il tuo stato):
- Ripristina : ripristina lo stato con cui è stato creato il tuo negozio
- Ripristina : torna all'ultimo stato di commit
- Sweep : rimuove tutte le azioni disabilitate che potresti aver attivato per errore
- Commit : rende lo stato corrente lo stato iniziale
La funzione di viaggio nel tempo non è efficiente nella produzione ed è intesa solo per lo sviluppo e il debug. Lo stesso vale per DevTools.
Redux rende i test molto più semplici perché utilizza JavaScript funzionale come base e piccole funzioni indipendenti sono facili da testare. Quindi, se è necessario modificare qualcosa nell'albero degli stati, importare solo un riduttore responsabile di quello stato e testarlo in isolamento.
Crea un'app
Per concludere questa guida introduttiva, costruiamo un'applicazione molto semplice utilizzando Redux e React. Per rendere più facile per tutti seguire, mi atterrò al semplice vecchio JavaScript, usando ECMAScript 2015 e 2016 il meno possibile. Continueremo la logica di accesso iniziata in precedenza in questo post. Questo esempio non utilizza alcun dato in tempo reale, perché lo scopo di questa app è mostrare come Redux gestisce lo stato di un'app molto semplice. Useremo CodePen.
1. Componente di reazione
Abbiamo bisogno di alcuni componenti e dati di React. Creiamo un componente semplice e rendiamolo sulla pagina. Il componente avrà un campo di input e un pulsante (è un modulo di accesso molto semplice). Di seguito, aggiungeremo del testo che rappresenta il nostro stato:
Guarda la Pen Intro to Redux di Alex Bachuk (@abachuk) su CodePen.
2. Eventi e azioni
Aggiungiamo Redux al progetto e gestiamo l'evento onClick
per il pulsante. Non appena l'utente effettua l'accesso, invieremo l'azione con il tipo LOGIN
e il valore dell'utente corrente. Prima di poterlo fare, dobbiamo creare un archivio e passargli una funzione riduttore come argomento. Per ora, il riduttore sarà solo una funzione vuota:
Guarda la Pen Intro to Redux - Step 2. Eventi e azioni di Alex Bachuk (@abachuk) su CodePen.
3. Riduttori
Ora che abbiamo attivato l'azione, il riduttore eseguirà quell'azione e restituirà un nuovo stato. Gestiamo l'azione LOGIN
restituendo uno stato di accesso e aggiungiamo anche un'azione LOGOUT
, in modo da poterla utilizzare in seguito. L' auth
reducer accetta due parametri:
- lo stato corrente (che ha il valore predefinito),
- l'azione.
Guarda la Pen Intro to Redux - Step 3. Reducers di Alex Bachuk (@abachuk) su CodePen.
4. Visualizzazione dello stato corrente
Ora che abbiamo lo stato iniziale (il valore predefinito in reducer) e il componente React pronto, vediamo come appare lo stato. Una buona pratica consiste nel ridurre lo stato alle componenti dei bambini. Poiché abbiamo un solo componente, passiamo lo stato dell'app come proprietà ai componenti di auth
. Per far funzionare tutto insieme, dobbiamo registrare il listener del negozio con un metodo helper di subscribe
, avvolgendo ReactDOM.render
in una funzione e passandolo a store.subscribe()
:
Vedere Pen Intro to Redux - Step 4. Visualizzazione dello stato corrente di Alex Bachuk (@abachuk) su CodePen.
5. Accedi e disconnetti
Ora che abbiamo i gestori delle azioni di accesso e disconnessione, aggiungiamo un pulsante di disconnessione e inviamo l'azione LOGOUT
. L'ultimo passaggio consiste nel gestire quale pulsante visualizzare il login o il logout spostando questo login al di fuori del metodo di rendering e visualizzando la variabile in basso:
Guarda la Pen Intro to Redux - Step 5. Login/Logout di Alex Bachuk (@abachuk) su CodePen.
Conclusione
Redux sta guadagnando terreno ogni giorno. È stato utilizzato da molte aziende (Uber, Khan Academy, Twitter) e in molti progetti (Apollo, WordPress' Calypso), con successo in produzione. Alcuni sviluppatori potrebbero lamentarsi del fatto che ci sono molte spese generali. Nella maggior parte dei casi, è necessario più codice per eseguire semplici azioni come clic sui pulsanti o semplici modifiche dell'interfaccia utente. Redux non è perfetto per tutto. Ci deve essere un equilibrio. Forse le azioni semplici e le modifiche dell'interfaccia utente non devono far parte dell'archivio Redux e possono essere mantenute a livello di componente.
Anche se Redux potrebbe non essere la soluzione ideale per la tua app o framework, ti consiglio vivamente di provarlo, specialmente per le applicazioni React.
Crediti immagine in prima pagina: Lynn Fisher, @lynnandtonic