2016-02-27 15 views
16

Sono nuovo di React e ancora più recente di Redux. Finora, avendo usato entrambi insieme per una piccola applicazione sandbox, mi piacciono.Redux - perché lo stato è tutto in un unico posto, persino lo stato che non è globale?

Quando si tratta di un'applicazione più grande, tuttavia, sto iniziando a chiedermi: Perché Redux mantiene l'intero stato dell'applicazione in un singolo archivio?

Se ho un'applicazione con molti pezzi diversi (e ognuno di quei pezzi ha ciascuno i loro componenti), sarebbe opportuno per me tenere ciascuno stato di quei pezzi a se stessi (nel componente di livello superiore di ogni pezzo) , purché il loro stato non influenzi le cose con altri componenti.

Non sono sicuro dei vantaggi di avere lo stato per tutto in un unico posto, quando pezzi di quello stato non hanno nulla a che fare con altri pezzi di esso. Se il componente A non è influenzato dallo stato del componente B, e viceversa, il loro stato non dovrebbe essere mantenuto nei loro componenti anziché nella radice?

Non è possibile avere lo stato che influisce globalmente nella radice e lo stato specifico di ciascun componente nei propri componenti? Sono preoccupato di lanciare tutto lo stato di componente specifico lungo tutta la catena verso un oggetto di stato globale (specialmente quando React enfatizza il flusso dall'alto verso il basso).

+1

Penso che ci sia [una discussione pertinente al riguardo sul loro GitHub] (https://github.com/reactjs/redux/issues/1385)? Non è stata data una risposta ufficiale, ma è in discussione - non sono sicuro che sia davvero d'aiuto. – aug

+0

cosa succede se ridisegnate la vostra app e lo stato non globale deve essere globale ora? – Theo

+0

@aug: Grazie per aver pubblicato. Una grande quantità di informazioni lì. Aiuta a rispondere alla domanda che ho su "Posso usare i negozi redux E reagire stato?" – Skitterm

risposta

8

Il vantaggio principale dello stato globale per un'applicazione di interfaccia utente è che è possibile monitorare ATOMICAMENTE le modifiche di stato dell'intera applicazione.

tldr; puoi sempre salvare e prevedere facilmente lo stato dell'app perché c'è un'unica fonte di verità.

Il problema con i componenti gestiti dallo stato autonomo è che creano una combinazione imprevedibile di stati possibili. Non è possibile stabilire facilmente in quale stato sarà la tua applicazione se XComponent cambierà se stesso perché dovresti wrangle YComponent e ZComponent e poi far loro conoscere lo stato degli altri in modo che possano prendere decisioni basate su quello e determinare lo stato di l'applicazione generale.

Ciò a cui questo si riduce in realtà è il contesto. Se ho una decisione che si basa sulla conoscenza dello stato di 3 parti separate dello stato dell'applicazione che non hanno una relazione diretta in termini di composizione UI, come faccio a ottenere il contesto per prendere quella decisione e comunicare il risultato a tutta l'applicazione ? Senza l'accesso a una rappresentazione di stato completa, non esiste un modo semplice per ottenere quell'aggregazione di contesto.

Redux (e altri modelli come il ratom in Reagent) risolvono questo con stato globale unificato. Le tue azioni sono solo messaggeri con cambiamenti di stato ma il tuo negozio è il detentore del contesto. Senza un solo negozio, i tuoi componenti sarebbero come i signori della guerra feudali che bisticciano sullo stato dei loro feudi liberamente collegati. Il negozio è il risultato di un'oligarchia strettamente unita (combineReducers()) che regola lo stato dell'applicazione con un pugno di ferro e tiene lontani gli insetti :)

Lo stato globale funziona bene per l'interfaccia utente e risolve molti problemi, anche se è contro- pratica intuitiva o addirittura cattiva per altri tipi di software. Detto questo, è stato notato frequentemente che non TUTTO lo stato dell'applicazione deve essere nel negozio Redux. Inoltre, puoi cancellare i dati che non sono più utili/pertinenti. Infine, lo stato che è SOLO pertinente per un determinato componente (e per il suo comportamento/visualizzazione) non deve necessariamente riflettersi nello store globale (necessariamente).

L'astrazione di separazione delle preoccupazioni in Redux è il riduttore perché è possibile creare più riduttori e combinarli per creare la catena logica per gli aggiornamenti del negozio.

Con i riduttori, si sta ancora "separando" la logica di stato nel codice, ma in realtà viene considerata come un singolo albero durante l'esecuzione. Ciò mantiene i cambiamenti di stato prevedibili e atomici, ma consente una buona organizzazione, incapsulamento e separazione delle preoccupazioni.

+0

Grazie. Questo ha molto senso. Sembra che ci sia un lato negativo nel rendere riutilizzabili i componenti di "Reagire con redux". Sono d'accordo con te sullo stato centralizzato, ma vedo che se volessi usare il componente in un'altra app, avresti bisogno di fare molti cavi insieme (i riduttori, la struttura dello stato deve essere simile quando si mappa lo stato in i tuoi oggetti di scena), mentre se lo stato fosse gestito localmente nel componente potresti più o meno lasciare il componente in un'altra app React e andare avanti. – Skitterm

+1

Bene, pensateci per un secondo: se lo stato è gestito all'interno del componente, quando lo si rilascia in un'altra applicazione, in che modo tale applicazione personalizza il comportamento e le interazioni di quel componente? La risposta è che NON PUO 'NON MODIFICARE il componente. Se il componente è stateless (fondamentalmente stupido) e semplicemente emette eventi (azioni) e riceve oggetti di scena, è POSSIBILE rilasciarlo in qualsiasi applicazione e l'applicazione può fare affidamento su di esso per seguire ciecamente gli ordini senza interpretarli a causa di alcune regole di stato rimanenti dal suo domanda precedente. Ha senso? –

10

Perché spostiamo il nostro stato persistente in un database, invece di lasciare che ciascuno dei nostri componenti di back-end gestisca il loro stato in file separati?

Perché rende molto più semplice eseguire query, eseguire il debug e serializzare lo stato generale dell'applicazione.

Redux è stato ispirato da un linguaggio chiamato Elm, che promuove anche l'uso di un singolo modello. Il creatore di Elm ha un'ulteriore giustificazione sul perché questa è una qualità importante per le applicazioni.

C'è un'unica fonte di verità. Gli approcci tradizionali ti costringono a scrivere una quantità decente di codice personalizzato e soggetto a errori per sincronizzare lo stato tra molti diversi componenti stateful. (Lo stato di questo widget deve essere sincronizzato con lo stato dell'applicazione, che deve essere sincronizzato con qualche altro widget, ecc.) Inserendo tutto il tuo stato in una posizione, elimini un'intera classe di bug in cui due componenti ottengono in stati contraddittori. Pensiamo anche che finirai per scrivere meno codice. Questa è stata la nostra osservazione in Elm finora.

ho trovato questo concetto molto più facile da imparare e capire, mentre affrontando da ClojureScript di Re-frame e guardare David Nolen di videos on Om Next. Il Re-frame README per il progetto è anche una grande risorsa di apprendimento.

Ecco alcuni dei miei consigli personali sul perché lo stato globale è una soluzione più elegante.

componenti più semplici

uno scenario comune che si pone in molte applicazioni basate su componenti stateful, è la necessità di modificare lo stato che vive in un altro componente.

Ad esempio, facendo clic su un pulsante di modifica in un componente NameTag dovrebbe aprire un editor che permette all'utente di modificare alcuni dati che vive nello stato di un Profile componente (un genitore di NameTag). Il modo per risolvere questo problema è quello di tramandare i callback del gestore, che quindi propagano i dati di backup dell'albero dei componenti. Questo schema si traduce in confusi flussi di dati secondari all'interno del flusso di dati unidirezionale esistente delle applicazioni React.

Con uno stato globale, i componenti inviano solo azioni che attivano gli aggiornamenti a tale stato. Sia i componenti che le azioni possono essere parametrizzati per inviare all'utente informazioni contestuali (ad esempio, qual è l'ID dell'utente di cui devo modificare il nome).

Non devi pensare molto a come comunicare i cambiamenti allo stato, perché sai esattamente dove si trova lo stato, e le azioni sono il meccanismo predefinito per inviare le modifiche lì.

funzioni pure

Quando il tuo stato dell'applicazione vive in un unico luogo, i componenti che lo rendono in grado di essere funzioni puri che prendono Stato come argomento. Guardano solo i dati e restituiscono una vista che può inviare azioni per fare aggiornamenti.

Queste funzioni sono trasparenti di riferimento, il che significa che per ogni dato insieme di input, c'è sempre lo stesso output. Questo è l'ideale per i test e si finisce con componenti che sono semplici da testare.

serializzazione

In un tradizionale React applicazione con componenti stateful, serializzare l'intero stato applicazione sarebbe un incubo. Ciò implicherebbe l'attraversamento dell'intero albero dei componenti e l'estrazione del valore di stato da ciascun componente, prima di collezionarli tutti in una struttura dati e codificarli.

Ri-gonfiare i componenti con uno stato serializzato significherebbe una procedura simile, eccetto che dovresti anche capire quali tipi di componenti erano responsabili di quali dati, in modo da poter ricreare accuratamente l'albero dei componenti. Ciò significherebbe anche memorizzare ulteriori informazioni sui tipi di componenti nel tuo stato.

Con lo stato globale, è possibile semplicemente codificarlo e decodificarlo esattamente dove si trova.

Undo/Redo

Per implementare undo/redo con lo stato globale, è necessario memorizzare gli stati in una lista, invece di sostituire l'ultimo quando aggiorna. Un puntatore indice può controllare lo stato corrente in cui ci si trova.

Con componenti stateful, questo richiederebbe a ciascun componente di implementare questo meccanismo. Non solo questo è un lavoro extra, ma crea anche un altro punto nella tua applicazione per l'introduzione di bug. Il miglior codice non è un codice, come si suol dire.

Riproduzione Azione

In Redux (e il modello di flusso in generale) siamo in grado di tenere traccia delle azioni che sono state giocate, poi riprodurli in un altro contesto per produrre esattamente nello stesso stato.

Se si introduce lo stato locale del componente, è possibile dire addio a questo. Gli aggiornamenti allo stato locale possono provenire da gestori di eventi DOM, richieste di rete, operazioni asincrone (e molto altro). Queste operazioni non possono essere serializzate, il che significa che non possono essere riprodotte neanche.

+8

Vorrei sottolineare che ** non suggeriamo di andare all-in mantenendo tutto lo stato in Redux. Quando porta a un codice complicato, non farlo. ** Ad esempio, non metterei cose come "è il menu a discesa attivato" in Redux perché è completamente irrilevante per qualsiasi altro componente. –

Problemi correlati