Tutorial > Primi passi con Redux

Primi passi con Redux

Pubblicato il: 05 dicembre 2022

Javascript Redux Sviluppo

Introduzione

Redux è un container di stati per App scritte in Javascript. Esso funge da libreria all'interno delle App in React ma può essere anche associato ad altri framework di Javascript.

Redux supporta lo sviluppo di applicazioni grandi e complesse che potrebbero necessitare dei vantaggi offerti da questo container.

Redux fa perno su tre concetti fondamentali:

  • reducers
  • actions
  • action creators
  • store

Reducer

Un reducer è una funzione che prende lo stato precedente e un'azione come input e restituisce un nuovo stato come output. Un'azione è un oggetto che possiede un tipo e un payload opzionale.

Eccoti un esempio di Reducer:

function Reducer(previousState, action) => {
  // use the action type and payload to create a new state based on
  // the previous state.
  return newState;
}

I reducers permettono di specificare come lo stato delle applicazioni cambia in risposta alle azioni che sono dispiegate nello store.

Se la tua app possiede stati multipli, allora potrà possedere reducers multipli. Le funzionalità principali della tua app dovrebbero possedere un proprio reducer.

Action

Una action è un oggetto in Javascript semplice che rappresenta il carico di informazioni che vengono inviati dalla applicazione al tuo store. Ogni azione possiede un tipo e un payload opzionale.

I maggiori cambiamenti nelle applicazioni che usano redux iniziano con un evento che è scatenato da un user direttamente o indirettamente. Gli eventi come il click su un bottone, selezione di oggetti o passaggio del cursore su un particolare elemento scatenano delle richieste AJAX che rimandano indietro alcuni dati. Le possibilità di associare un'azione come risposta a un evento sono tantissime.

Le azioni sono create da un action creator.

Action Creator

Nel Redux, un action creator è una funzione che restituisce un oggetto action. Potrà sembrare non indispensabile ma i creator permettono di inviare un oggetto azione a tutti i different reducers presenti nell'app, garantendo un beneficio in portabilità e nel test.

A seconda della azione inviata ai reducers, essi possono restituire una nuova versione del loro stato, che viene passata nello stato della applicazione e,infine, nella app React, ricaricando i componenti.

Quindi, seguendo la definizione data di Action Creator, ipotizziamo sia una funzione specificata con una sintassi simile:

export function newTask({ task }) {
  return {
    type: 'NEW_TASK',
    payload: {
      task,
      completed: false
    },
  }
}

// esempio di valore di ritorno:
// {
//   type: 'NEW_TASK',
//   todo: { task: 'Prepara valigia viaggio', completed: false },
// }

Un esempio di come un reducer si comporta con una azione di tipo NEW_TASK:

export default function(state = initialState, action) {
  switch (action.type) {
    case 'NEW_TASK':
      const newState = [...state, action.payload];
      return newState;


    default:
      return state;
  }
}

A seconda del coinvolgimento con l'azione interessata, i reducers restituiranno lo stesso stato di prima o un nuovo stato. È bene sapere che tutti i reducers processeranno l'azione ma solo alcuni cambieranno il loro stato.

Infine, verrà eseguito nuovamente il rendering delle componenti:

{
  currentTask: { task: 'Prepara valigia viaggio', completed: false },
  todos: [
    { task: 'Prepara valigia viaggio', completed: false },
    { task: 'Lascia cane alla pensione', completed: true }
  ],
}

Combinare i Reducers

Redux ti offre la funzione combineReducers per eseguire due compiti:

  • Genera una funzione che chiama i nostri reducer con la porzione di stato selezionata in base alla loro chiave.
  • Quindi combina nuovamente i risultati in un unico oggetto.

Lo Store

Lo store è l'oggetto che include le action e i reducers. In sostanza, gestisce le informazioni su ciò che succede e i cambi di stato in risposta a tali eventi.

I compiti dello store sono:

  • Permesso dell'accesso tramite il getState()
  • Permesso di aggiornamento di uno stato tramite dispatch(action)
  • Mantenimento dello stato dell'intera applicazione
  • Registra i listener tramite subscribe(listener)
  • Deregistra i listener tramite la funzione restituita da subscribe(listener)

Per creare uno store sarà sufficiente passargli una combinazione di reducers per consentirgli poi di dispiegare le azioni.

import { createStore } from 'redux';
import todoReducer from './reducers';

const store = createStore(todoReducer);
store.dispatch(addTodo({ task: 'Finisci di leggere la guida'}));
store.dispatch(addTodo({ task: 'Applica i concetti imparati su un tuo progetto!' }));
// ...

Flusso dei Dati in Redux

Redux possiede un flusso dei dati unidirezionale fisso, il che consente di comprendere meglio il ciclo di vita dei dati all'interno della tua applicazione.

I passi del ciclo di vita dei dati in Redux sono i seguenti

export default const currentTask(state = {}, action){
  // deal with this piece of state
  return newState;
};

export default const todos(state = [], action){
  // deal with this piece of state
  return newState;
};

export default const todoApp = combineReducers({
  todos,
  currentTask,
});
  1. Un evento all'interno della tua applicazione fa scattare una chiamata a store.dispatch(actionCreator(payload))
  2. Lo store chiama il reducer root con lo stato corrente e la azione
  3. Il root reducer combina l'output di diversi reducers in un unico albero di stati

Quando l'azione sarà emessa, todoApp chiamerà entrambi i reducers e combinerà i set di risultati in un unico albero di stati:

return {
  todos: nextTodos,
  currentTask: nextCurrentTask,
};

Completato il salvataggio dell'albero di stati da parte di Redux, il nuovo albero di stati sarà il prossimo della tua app.

Conclusioni

Al termine della guida, avrai completato la tua infarinatura di Redux. Ti consigliamo di approfondire i concetti imparati e molti altri sulla Documentazione ufficiale di Redux.