Redux non è solo uno stato globale glorificato?


86

Quindi ho iniziato a imparare React una settimana fa e sono inevitabilmente arrivato al problema dello stato e di come i componenti dovrebbero comunicare con il resto dell'app. Ho cercato in giro e Redux sembra essere il sapore del mese. Ho letto tutta la documentazione e penso che in realtà sia un'idea piuttosto rivoluzionaria. Ecco i miei pensieri su di esso:

Lo stato è generalmente riconosciuto come piuttosto malvagio e una grande fonte di bug nella programmazione. Invece di spargere tutto nella tua app, Redux dice perché non concentrarti tutto in un albero di stato globale che devi emettere azioni per cambiare? Sembra interessante. Tutti i programmi hanno bisogno di uno stato, quindi inseriamolo in uno spazio impuro e modifichiamolo solo dall'interno in modo che i bug siano facili da rintracciare. Quindi possiamo anche associare in modo dichiarativo singoli pezzi di stato ai componenti React e ridisegnarli automaticamente e tutto è bello.

Tuttavia, ho due domande su questo intero progetto. Per prima cosa, perché l'albero degli stati deve essere immutabile? Diciamo che non mi interessa il debug del viaggio nel tempo, il ricaricamento a caldo e ho già implementato undo / redo nella mia app. Sembra così ingombrante dover fare questo:

case COMPLETE_TODO:
  return [
    ...state.slice(0, action.index),
    Object.assign({}, state[action.index], {
      completed: true
    }),
    ...state.slice(action.index + 1)
  ];

Invece di questo:

case COMPLETE_TODO:
  state[action.index].completed = true;

Per non parlare del fatto che sto creando una lavagna online solo per imparare e ogni cambiamento di stato potrebbe essere semplice come aggiungere un tratto di pennello all'elenco dei comandi. Dopo un po '(centinaia di pennellate) la duplicazione dell'intero array potrebbe iniziare a diventare estremamente costosa e richiedere molto tempo.

Sono d'accordo con un albero di stato globale indipendente dall'interfaccia utente che viene modificato tramite azioni, ma è davvero necessario che sia immutabile? Cosa c'è di sbagliato in una semplice implementazione come questa (bozza molto approssimativa. Scritta in 1 minuto)?

var store = { items: [] };

export function getState() {
  return store;
}

export function addTodo(text) {
  store.items.push({ "text": text, "completed", false});
}

export function completeTodo(index) {
  store.items[index].completed = true;
}

È ancora un albero di stato globale mutato tramite azioni emesse ma estremamente semplice ed efficiente.


2
"Per prima cosa, perché l'albero dello stato deve essere immutabile?" --- allora devi fornire un algoritmo per determinare se i dati sono cambiati. Non è possibile implementarlo per una struttura dati arbitraria (se è modificabile). Prendi immutablejse usa return state.setIn([action.index, 'completed'], true);per ridurre il boilerplate.
zerkms

1
PS:return state.map(i => i.index == action.index ? {...i, completed: true} : i);
zerkms

Risposte:


53

Redux non è solo uno stato globale glorificato?

Ovviamente è. Ma lo stesso vale per ogni database che hai mai usato. È meglio trattare Redux come un database in memoria, da cui i componenti possono dipendere in modo reattivo.

L'immutabilità consente di controllare se qualche sottoalbero è stato alterato in modo molto efficiente perché si semplifica fino a un controllo dell'identità.

Sì, la tua implementazione è efficiente, ma l'intero dominio virtuale dovrà essere nuovamente renderizzato ogni volta che l'albero viene manipolato in qualche modo.

Se stai usando React, alla fine eseguirà una differenza contro il dominio reale ed eseguirà manipolazioni ottimizzate in batch minime, ma il rendering completo dall'alto verso il basso è ancora inefficiente.

Per un albero immutabile, i componenti senza stato devono solo controllare se la sottostruttura da cui dipende, differiscono nelle identità rispetto ai valori precedenti e, in tal caso, il rendering può essere completamente evitato.


3
Non è forse un'ottimizzazione prematura? Inoltre, come sappiamo che il costo della duplicazione costante di oggetti immutabili è inferiore al ri-rendering del DOM (inoltre il DOM virtuale di React non mitigerebbe pesantemente questo costo?)
Ryan Peschel

3
Bene, le librerie GUI questo tipo di ottimizzazione per molto tempo (Fare riferimento: bitquabit.com/post/the-more-things-change ) Inoltre la gestione di una struttura dati immutabile non è così costosa come potresti pensare, ad esempio se un nodo viene cambiato, solo una singola catena di genitori deve essere concatenata - il resto dei nodi rimane inalterato. Quindi non duplichiamo l' intera struttura dati per ogni azione: riutilizziamo i sottocomponenti che non sono cambiati per costruire una nuova struttura dati.
lorefnon

4
Anche Reacts Virtual DOM non è esattamente magia nera - Citando dai documenti di React: "La generazione del numero minimo di operazioni per trasformare un albero in un altro è un problema complesso e ben studiato - Gli algoritmi allo stato dell'arte hanno una complessità nell'ordine of O (n3) dove n è il numero di nodi nell'albero. "
lorefnon

2
Il motivo per cui React è in grado di funzionare molto meglio in pratica è perché: React si basa sull'euristica - quindi: "Se non fornisci chiavi stabili (usando Math.random () per esempio), tutti i sottoalberi verranno essere ri-renderizzato ogni singola volta. Dando agli utenti la possibilità di scegliere la chiave, hanno la possibilità di spararsi ai piedi. " Quindi, proprio come puoi aiutare React fornendo chiavi stabili, allo stesso modo puoi aiutare React fornendo oggetti di scena immutabili.
lorefnon

1
Per quanto riguarda la tua gamma di pennellate, fai riferimento a: facebook.github.io/immutable-js/docs/#/List Citazioni da documenti: le liste sono raccolte dense e indicizzate, molto simili a un array JavaScript. Le liste implementano Deque, con l'aggiunta e la rimozione efficienti sia dalla fine (push, pop) che dall'inizio (unshift, shift).
lorefnon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.