Spigoli in Redux – 1. Switch case
I primi esempi di reducer, a partire da quelli che si trovano nella documentazione ufficiale, suggeriscono una implementazione basata su switch case:
function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } }
A parte un personale fastidio rispetto a questo costrutto, penso che un reducer strutturato in questo modo sia poco scalabile. Sicuramente è un modo diretto ed efficace per illustrare il concetto in un caso semplice. Si rischia però che questa struttura venga mantenuta man mano che il reducer cresce e quindi gestisce più casi.
Il rischio è quello di arrivare ad una funzione composta da tante righe, aggravata dal fatto che lo switch-case si presta a pratiche a mio avviso fuorvianti come il fall-through dei case.
Per risolvere questi problemi uso una mappa che contiene delle funzioni che implementano i singoli casi da gestire. Siccome queste funzioni servono per rispondere ad una azione che arriva al reducer, le ho chiamate reazioni.
Facendo il parallelo con il reducer mostrato sopra, le reazioni sarebbero le seguenti:
const reactions = { INCREMENT: state => state + 1 DECREMENT: state => state - 1 }
Per utilizzare queste reazioni uso una funzione di secondo ordine che genera il reducer:
const reducerFactory = (initialState, reactions) => { return (state = initialState, action) => const reaction = reactions[action.type]; if (reaction) { return reaction(state, action); } return state; };
Questa funzione prende lo stato iniziale e la lista di reazioni e restituisce un reducer: una funzione che accetta uno stato e una azione e restituisce lo stato aggiornato.
In questo modo la funzione factory può essere testata una volta sola, lasciando da testare le singole reazioni che risultano però molto piccole, pure e facili da testare.
Con questa utility il reducer può essere istanziato come segue:
const counter = reducerFactory(0, reactions)