Userò il seguente esempio popolare di elenco di cose da fare per la dimostrazione. Diciamo che volevo creare un elenco di cose da fare molto semplice con questa struttura come stato dell'app:
{
todos: {
todoKey1: {
content: "todoKey1 content",
...
},
todoKey2: ...
}
}
A causa della natura ricorsiva dei riduttori, possiamo separare i riduttori in file diversi:
// reducers/app.js:
import todos from "./todos";
export default function app(prev={}, action){
return {
todos: todos(prev.todos, action)
};
}
// reducers/todos.js:
import todo from "./todo";
export default function todos(prev={}, action){
switch(action.type){
case "ADD_TODO":
return {
...prev,
[action.id]: todo(undefined, action)
};
default:
return prev;
}
}
// reducers/todo.js:
export default function todo(prev={}, action){
switch(action.type){
case "ADD_TODO":
return {content: action.content};
default:
return prev;
}
}
Tutto sembra buono finora - bello e organizzato. È qui che arriva la mia domanda: non voglio includere la nuova chiave per il nuovo todo nell'azione. Invece, voglio che l'azione sia molto pura, in cui dovrebbe descrivere solo l'azione (aggiungendo un nuovo oggetto da fare). id
è irrilevante.
Vorrei che la chiave venisse generata automaticamente ogni volta che aggiungo un oggetto todo e quindi ho modificato la struttura dello stato per includere next_available_id
che indica quale dovrebbe essere la chiave nel prossimo articolo da utilizzare:
{
next_available_id: 0,
todos: {
todoKey1: {
content: "todoKey1 content",
...
},
todoKey2: ...
}
}
Questo rompe i simpatici riduttori ricorsivi che ho avuto da quando ora todos()
non ha id
per creare la nuova voce e l'azione non ha id
. Invece, dovrò combinare il riduttore in todos.js
in app.js
:
// reducers/app.js:
import todo from "./todo";
export default function app(prev={}, action){
switch(action.type){
case "ADD_TODO":
let todos = prev.todos || {};
return {
...prev,
next_available_id: prev.next_available_id + 1,
todos: {
...todos,
[prev.next_available_id]: todo(undefined, action)
}
};
default:
return prev;
}
}
Possibili soluzioni a cui posso pensare:
- Invio di più azioni: una per l'incremento di
next_available_id
e un'altra per l'effettiva creazione di un punto.- Pro:
app.js
etodos.js
possono rimanere separati - Con: Questo può diventare davvero disordinato nell'applicazione reale poiché ci sarebbero molte azioni extra
- Pro:
- Modifica l'azione stessa prima di passare a
todos
.- Pro: elimina la necessità di un'azione aggiuntiva
- Con: le azioni devono essere immutabili
Mi sento come se mi mancasse qualcosa qui. Quale sarebbe il modo standard di gestire situazioni come questa?