Quando Redux o Context API
Provo a spiegare perché l'uno non esclude l'altro, quali sono i benefici e cosa risolvono
Gli state manager servono ancora?
Se sei finito su questo articolo con questa specifica domanda, forse ti conviene leggere questo articolo più recente.
Creare componenti in React è facile. Il problema è scegliere il componente a cui affidare alcune logiche importanti. Come spesso ho letto sulla documentazione ufficiale e su stackoverflow, è bene non esagerare con i componenti stateful perché in termini prestazionali questo può presentare un conto (alle volte salatissimo) a lungo termine. Optando per questa scelta il problema che si para davanti è il seguente:
Componente
<A />
detiene le logiche da distribuire ai componenti figli;Componente
<B />
figlio di<A />
deve smistare alcuni handler sui propri componenti;Componente
<C />
,<D />
hanno bisogno degli handler provenienti da<A />
smistati da<B />
;Potremmo andare all’infinito.
E’ già abbastanza palese dove voglio arrivare: questo tipo di architettura soffre di una problematica chiamata prop drilling. Per risolvere ci viene in soccorso la context API messa a punto da React, qualcosa che permette allo sviluppatore di passare da <A />
a <C />
o <D />
senza passare da <B />
. In realtà nella casistica appena mostrata sarebbe ancora accettabile ovviare senza la context API, ma non vorrei dilungarmi inutilmente.
La context API risulta perfetta per la creazione di componenti generici o librerie, perché la problematica è legata a componente genitore - figlio - nipote - pronipote e non vi è alcuna necessità di rendere uno state accessibile a tutti i componenti dell’intera applicazione. Cosa assai diversa appunto, è distribuire oggetti su aree diverse di un’applicazione. La problematica che nella mia esperienza ho riscontrato è che più l’applicazione cresce e più si perde il controllo dei cambiamenti di stato dei componenti. Una cosa che più tra tutte sta nelle priorità di un buon sviluppatore è avere ben chiaro cosa diavolo succede ad ogni cambiamento di stato.
La risposta a quest’altra problematica è Redux.
Un po’ d’ordine con Redux
Redux è una libreria che si occupa di gestire tanti state, detti reducer, centralizzati in uno store (ossia un oggetto che li contiene tutti, separandone le logiche) condiviso con l’intera applicazione e si rivela particolarmente utile per diversi aspetti quali debugging, maggiore astrazione e test separati.
Per poter utilizzarlo all’interno di un progetto in React viene utilizzato il modulo react-redux
oltre a redux
, un HOC (high order component) che si occupa di mettere in comunicazione lo store con il component attraverso l’apposita funzione connect
che accetta come argomento le due funzioni mapStateToProps
e mapDispatchToProps
, rispettivamente: “mappa lo state di redux e usale come props del componente”; “mappa i dispatcher di redux come props del componente”.
Con questo non si preclude allo sviluppatore di optare per gli state locali, anzi, è sempre bene tenere tutto il più atomico possibile. Redux non si sostituisce agli state in tutti i componenti dell’applicazione (una cosa che tendenzialmente ho visto spesso in alcuni progetti), ma deve essere utilizzato unicamente per gestire dati condivisi con molti componenti, indipendentemente dal tipo di relazione.
Un caso d’uso comune: dopo l’autenticazione ho bisogno delle informazioni dell’utente autenticato ( es: avatar, nome ) in più parti della mia applicazione. Lo store in questo caso è il più indicato a mantenere questo tipo di informazioni.
Mannaggia quanto è verboso Redux…
E’ vero, si scrive molto ma è un compromesso che bisogna accettare (o pretendere!) ad occhi chiusi in un’applicazione medio grande specie se in team con più persone. Idealmente si potrebbe pensare ad un approccio più test driven, con una risorsa preposta a svilupare i servizi con Redux (action , reducer ed eventualmente saga o action creator) poi testarli e infine pubblicarli.
You Might Not Need Redux - Dan Abramov, co-fondatore di Redux: Link
Conclusioni
PRO di Redux
Con Redux hai una maggiore testabilità: è possibile testare lo store indipendentemente da tutta l ’applicazione isolandolo;
Con Redux puoi dividere i compiti: in un progetto medio-grande può esserci una persona preposta alla creazione di action, reducers e quant’altro;
Con Redux hai un livello di astrazione che ti permette di cambiare le API senza stravolgere la logica nei component;
Con Redux puoi gestire gli errori automatizzando un sistema di bug report (senza entrare nel merito del component) creando un middleware per Redux ad-hoc
Contro di Redux
Evitalo come la peste se lavori in un progetto piccolo e non hai la necessità di gestire molti dati da condividere su più parti dell’applicazione;
E’ verboso;
Inficia negativamente sulle performance
La documentazione ufficiale: https://reactjs.org/docs/context.html#when-to-use-context
Qui un articolo interessante: https://daveceddia.com/context-api-vs-redux/
Qui una discussione sui pro e i contro: https://stackoverflow.com/questions/49568073/react-context-vs-react-redux-when-should-i-use-each-one