Una volta individuato l'elenco delle attività disponibili per l'interfaccia, occorre definire le azioni che consentono la modifica, o meglio, la transizione di stato. Abbiamo detto che per Redux un'azione non è altro che un semplice oggetto JavaScript. Possiamo quindi definire le azioni per l'aggiunta e la rimozione di un'attività come mostrato di seguito:
let aggiungi ={
type: "ADD",
payload: {task: "Nuova attività"}
};
let rimuovi ={
type: "REMOVE",
payload: {taskId: 123}
};
Naturalmente potevamo scegliere di definire le azioni con una struttura diversa dal momento che, ricordiamo, Redux non pone vincoli sulla struttura dell'oggetto che definisce un'azione. In ogni caso, le azioni così definite pongono almeno due questioni:
- una riguarda l'uso diretto di stringhe per identificare il tipo di azione
- l'altra è relativa alla presenza di elementi variabili all'interno del corpo dell'azione.
Nel primo caso possiamo andare incontro a situazioni di errore quando ad esempio definiamo il tipo di un'azione con una stringa e poi dobbiamo riportare la medesima stringa nella definizione del reducer, come vedremo in seguito.
Il tipo d'azione verrà infatti analizzato dal reducer per identificare la transizione di stato da applicare. Un errore di battitura nella trascrizione della stringa che identifica il tipo di azione potrebbe introdurre malfunzionamenti non semplici da identificare.
Per evitare ciò è prassi comune definire delle costanti ed utilizzarle al posto delle stringhe nella definizione delle azioni, come mostrato dal seguente esempio:
const ADD = "ADD";
const REMOVE = "REMOVE";
let aggiungi ={
type: ADD,
payload: {task: "Nuova attività"}
};
let rimuovi ={
type: REMOVE,
payload: {taskId: 123}
};
Questo ci consente da un lato di ottenere eventuali suggerimenti sintattici da parte dell'IDE che utilizziamo e dall'altro di prevenire errori di battitura, dal momento che l'eventuale nome errato sarebbe immediatamente segnalato dal sistema.
Inoltre, nel caso in cui il reducer che utilizza le nostre azioni sia definito in un modulo diverso da quello in cui vengono definite le azioni, è opportuno definire le costanti un un modulo separato ed importarlo sia nel modulo che definisce le azioni che in quello che definisce il reducer.
Il secondo aspetto da analizzare riguarda la presenza di parti variabili all'interno del corpo dell'azione. Infatti, l'azione che consente l'aggiunta di un'attività alla nostra lista prevede che venga specificato il nome dell'attività, mentre l'azione di rimozione prevede che venga specificato l'identificatore dell'attività da rimuovere.
È evidente che queste informazioni non possono rimanere cablate nella definizione delle azioni, ma occorre parametrizzarle. Per fare ciò ricorriamo all'Action creator. Ricordiamo che un Action creator è una funzione che restituisce un'azione definita in base a determinati parametri. Nel nostro caso possiamo scrivere i nostri Action creator come mostrato di seguito:
const ADD = "ADD";
const REMOVE = "REMOVE";
function addAction(text) {
return {
type: ADD,
payload: {task: text}
};
}
function removeAction(id) {
return {
type: REMOVE,
payload: {taskId: id}
};
}
In questo modo abbiamo a disposizione una sorta di template per la generazione di azioni in base ai parametri passati. Quindi potremo creare le azioni viste in precedenza nel seguente modo:
let aggiungi = addAction("Nuova attività");
let rimuovi = removeAction(123);