Redux - Riduttori

I riduttori sono una funzione pura in Redux. Le funzioni pure sono prevedibili. I riduttori sono l'unico modo per cambiare stato in Redux. È l'unico posto dove puoi scrivere logica e calcoli. La funzione Reducer accetterà lo stato precedente dell'app e dell'azione inviata, calcolerà lo stato successivo e restituirà il nuovo oggetto.

Le seguenti poche cose non dovrebbero mai essere eseguite all'interno del riduttore:

  • Mutazione degli argomenti delle funzioni
  • Chiamate API e logica di routing
  • Chiamare una funzione non pura, ad esempio Math.random ()

La seguente è la sintassi di un riduttore:

(state,action) => newState

Continuiamo l'esempio di mostrare l'elenco degli elementi del prodotto su una pagina Web, discusso nel modulo dei creatori di azioni. Vediamo di seguito come scrivere il suo riduttore.

const initialState = {
   isLoading: false,
   items: []
};
const reducer = (state = initialState, action) => {
   switch (action.type) {
      case 'ITEMS_REQUEST':
         return Object.assign({}, state, {
            isLoading: action.payload.isLoading
         })
      case ‘ITEMS_REQUEST_SUCCESS':
         return Object.assign({}, state, {
            items: state.items.concat(action.items),
            isLoading: action.isLoading
         })
      default:
         return state;
   }
}
export default reducer;

In primo luogo, se non si imposta lo stato su "initialState", Redux chiama il riduttore con lo stato indefinito. In questo esempio di codice, la funzione concat () di JavaScript viene utilizzata in "ITEMS_REQUEST_SUCCESS", che non modifica l'array esistente; restituisce invece un nuovo array.

In questo modo, puoi evitare la mutazione dello stato. Non scrivere mai direttamente allo Stato. In "ITEMS_REQUEST", dobbiamo impostare il valore dello stato dall'azione ricevuta.

È già stato discusso che possiamo scrivere la nostra logica in un riduttore e dividerla sulla base dei dati logici. Vediamo come possiamo dividere i riduttori e combinarli insieme come riduttori di radice quando si tratta di un'applicazione di grandi dimensioni.

Supponiamo di voler progettare una pagina web in cui un utente possa accedere allo stato dell'ordine del prodotto e visualizzare le informazioni sulla lista dei desideri. Possiamo separare la logica in diversi file di riduttori e farli funzionare in modo indipendente. Supponiamo che l'azione GET_ORDER_STATUS venga inviata per ottenere lo stato dell'ordine corrispondente a un ID ordine e un ID utente.

/reducer/orderStatusReducer.js
import { GET_ORDER_STATUS } from ‘../constants/appConstant’;
export default function (state = {} , action) {
   switch(action.type) {
      case GET_ORDER_STATUS:
         return { ...state, orderStatusData: action.payload.orderStatus };
      default:
         return state;
   }
}

Allo stesso modo, supponiamo che l'azione GET_WISHLIST_ITEMS venga inviata per ottenere le informazioni sulla lista dei desideri dell'utente rispettiva di un utente.

/reducer/getWishlistDataReducer.js
import { GET_WISHLIST_ITEMS } from ‘../constants/appConstant’;
export default function (state = {}, action) {
   switch(action.type) {
      case GET_WISHLIST_ITEMS:
         return { ...state, wishlistData: action.payload.wishlistData };
      default:
         return state;
   }
}

Ora, possiamo combinare entrambi i riduttori utilizzando l'utility Redux combinationReducers. I combinationReducers generano una funzione che restituisce un oggetto i cui valori sono differenti funzioni di riduzione. È possibile importare tutti i riduttori nel file di riduzione dell'indice e combinarli insieme come un oggetto con i rispettivi nomi.

/reducer/index.js
import { combineReducers } from ‘redux’;
import OrderStatusReducer from ‘./orderStatusReducer’;
import GetWishlistDataReducer from ‘./getWishlistDataReducer’;

const rootReducer = combineReducers ({
   orderStatusReducer: OrderStatusReducer,
   getWishlistDataReducer: GetWishlistDataReducer
});
export default rootReducer;

Ora puoi passare questo rootReducer al metodo createStore come segue:

const store = createStore(rootReducer);