Redux: Frage: Wie kann man zwischen dem Store von Redux und dem Status von React wählen?

Erstellt am 27. Jan. 2016  ·  26Kommentare  ·  Quelle: reduxjs/redux

question

Hilfreichster Kommentar

Verwenden Sie Reagieren für einen kurzlebigen Status, der für die App global nicht wichtig ist und nicht auf komplexe Weise mutiert. Zum Beispiel ein Umschalten in einem UI-Element, ein Formulareingabestatus. Verwenden Sie Redux für Zustände, die global wichtig sind oder auf komplexe Weise mutiert sind. Zum Beispiel zwischengespeicherte Benutzer oder ein Post-Entwurf.

Manchmal möchten Sie vom Redux-Status in den React-Status wechseln (wenn das Speichern in Redux umständlich wird) oder umgekehrt (wenn mehr Komponenten Zugriff auf einen Status haben müssen, der früher lokal war).

Als Faustregel gilt: Tun Sie, was weniger umständlich ist.

Alle 26 Kommentare

Verwenden Sie Reagieren für einen kurzlebigen Status, der für die App global nicht wichtig ist und nicht auf komplexe Weise mutiert. Zum Beispiel ein Umschalten in einem UI-Element, ein Formulareingabestatus. Verwenden Sie Redux für Zustände, die global wichtig sind oder auf komplexe Weise mutiert sind. Zum Beispiel zwischengespeicherte Benutzer oder ein Post-Entwurf.

Manchmal möchten Sie vom Redux-Status in den React-Status wechseln (wenn das Speichern in Redux umständlich wird) oder umgekehrt (wenn mehr Komponenten Zugriff auf einen Status haben müssen, der früher lokal war).

Als Faustregel gilt: Tun Sie, was weniger umständlich ist.

Verwenden Sie für Daten, die über Netzwerkanforderungen abgerufen werden, immer Speicher, um das serverseitige Rendern zu unterstützen (wenn Sie der Meinung sind, dass dies das ultimative Ziel ist), oder Sie können nicht rehydrieren.

Damit dieser Zustand von zwei oder mehr Containern abgehört werden kann, sollte er auch in Geschäften sein?

Ich stimme @gaeron hinsichtlich der Unterscheidung zwischen kurzlebig und hartnäckig zu. Aber ich denke tatsächlich in drei Kategorien darüber nach . Einer ist der UI-Zustand , über den er spricht, und ich halte ihn auch für kurzlebig. Ein anderer ist der Anwendungsstatus, der wirklich der beständige Kern der Anwendung ist. Aber ein dritter, der dazwischen liegt, ist der Routing-Status . Ich verwende den Begriff "Routing", weil er den Leuten vertraut ist, aber ich abstrahiere ihn zu einem "Ansichtsauswahl" -Zustand, da ich denke, dass er Desktop, Web und Mobile besser umfasst.

Nun könnte man argumentieren, dass dies der UI-Status ist, da er entscheidet, was die Leute sehen (ähnlich wie zum Beispiel der Status von Registerkarten). Aber ich sehe zwei Unterschiede. Der erste ist, dass der Status serialisiert (dh als URL) und an andere Personen gesendet wird. Die Dinge sollten also im Routenstatus ablaufen, wenn Sie möchten, dass die Benutzer direkt mit diesem bestimmten UI-Status "tief verknüpfen" können . Das zweite ist, dass in vielen Fällen der anfängliche Routenstatus oder eine Änderung der Route eine Änderung des Anwendungsstatus auslöst (dh das Laden der anzuzeigenden Daten). Natürlich machen Aktionen in der Benutzeroberfläche dasselbe. Aber der Unterschied, den ich mache, ist, dass Sie einen Routenstatus ohne Ansicht oder Rendering haben können (und sollten), um die "Anwendungslogik" um Änderungen im

In welcher Beziehung steht dies zur Frage von Redux vs. React für das State Management? Der Anwendungsstatus ist die Domäne von Redux und der UI-Status ist die Domäne von React. Der Routing-Status sollte (meiner Meinung nach) von Redux verwaltet werden, obwohl er als UI-Status angesehen werden kann (siehe die eingebetteten Links für weitere Erläuterungen, warum ich das denke).

Um es klar auszudrücken , gilt

Der Anwendungsstatus ist die Domäne von Redux und der UI-Status ist die Domäne von React.

Beachten Sie, dass ich dies nicht behaupte. Ich denke, es ist in Ordnung, sowohl einen App-Status in React als auch einen UI-Status in Redux beizubehalten. Ich denke nicht, dass sie durch Domänen getrennt werden sollten.

Wenn Sie mit Redux eine App erstellen, sollten Sie den einzelnen Statusbaum berücksichtigen. Setzen Sie dort auch den UI-Status. Wenn es jedoch langweilig und frustrierend wird, haben Sie keine Angst, den Komponenten einen Zustand zu verleihen. Mein Punkt ist, dass Sie einen einzelnen Statusbaum verwenden, es sei denn, dies ist umständlich, und dies nur tun, wenn dies die Dinge für Sie vereinfacht, anstatt sie zu komplizieren. Das ist die einzige Richtlinie.

Erstens wollte ich @gaearon auf keinen stecken , tut mir leid.

Zweitens stimme ich @gaearon voll und ganz zu. Ich glaube auch fest an einen einzigen Zustandsbaumansatz. Als ich über den UI-Status sprach, hatte ich wirklich kleine Dinge im Kopf (wie die aktuell ausgewählte Registerkarte), bei denen es möglicherweise nicht wirklich so relevant für den Anwendungsstatus ist (genau hat @gaearon besprochen).

Lassen Sie mich also meine Position klarstellen. Ich bin damit einverstanden, dass so ziemlich alles in Redux sein sollte , einschließlich des Routenstatus (wie ich es in den Routenstatus ausdrücklich erwähnt und ihn unterschieden, weil ich denke (und Sie können ihn in diesem TodoMVC sehen Implementierung), dass es definitiv in Redux gehört (und überhaupt nicht mit dem Rendern verbunden sein sollte) und definitiv nicht "UI-Status" ist.

Für React-Komponenten verwende ich selten state. Ich bevorzuge die Verwendung von Requisiten, um Informationen zum Rendern zu erhalten und um Abschlüsse zu erhalten, die ich aufrufen kann, um Änderungen außerhalb meiner Komponente auszulösen. Es gibt einige seltene Umstände, unter denen ich Zustände in Komponenten einführe, um das Leben zu erleichtern, aber ich versuche, dies zu vermeiden. Ich hoffe das klärt die Dinge.

Ich denke, diese Frage ist wirklich subjektiv und kompliziert, deshalb habe ich heute mit meinem Team eine schwere Entscheidung getroffen.

  • Für nicht wiederverwendbare Container, die eine Verbindung zu Redux haben, legen Sie einfach alles in den Redux-Speicher, selbst wenn ein winziger UI-Status vorliegt, wie wenn ein Modal geöffnet ist, verwenden Sie this.setState nicht mehr.
  • Verwenden Sie für wiederverwendbare Komponenten, die nichts mit Redux zu tun haben, den Status React.

Und jetzt implementieren wir einige Helfer, um die Verwaltung des winzigen UI-Status zu vereinfachen.

@gaearon @ lionng429 @xogeny Gibt es Nachteile, die Sie sich für diesen Ansatz

@inetfuture Ich neige dazu, den Anwendungsstatus (Redux) etwas beurteilen, da ich TypeScript verwende und einen Typ für meinen Anwendungsstatus ganz unten definiere. Davon abgesehen bin ich bei der Entwicklung von Komponentenbibliotheken dazu gekommen, die gesamte Statusmanipulation vom Rendering zu trennen (weitere Informationen finden Sie unter den Links in früheren Kommentaren). Dies bedeutet, dass ich selbst für allgemeine Komponenten, die nicht trivial sind, den Status vollständig externalisiere. Ich gebe im Allgemeinen alles durch Requisiten (sowohl Zustände als auch Schließungen zur Manipulation des Zustands). Auf diese Weise kann ich es einfach in meinen Anwendungsstatus einbinden. Ein Teil davon ist zweifellos ein Artefakt der Verwendung von TypeScript und der Tatsache, dass nicht nur combineReducers und connect um Dinge einzubinden (und zumindest die Typeinschränkungen beizubehalten). Dies ist also wahrscheinlich kein repräsentativer Standpunkt. Aber ich werde sagen, warum Sie sagen "Legen Sie einfach alles in den Redux-Laden", ich würde mir Sorgen machen, dass Sie am Ende ein Küchenspülbecken haben. Ich denke, die Tatsache, dass meine Verwendung von TypeScript bedeutet, dass das Erweitern des Anwendungsstatus einige Anstrengungen erfordert, ist nicht unbedingt eine schlechte Sache, da ich mich entscheiden muss, ob ich das wirklich brauche. anstatt Sachen einfach stapeln zu lassen.

Als alternativer Gedanke: Der lokale Komponentenstatus kann für gesteuerte Eingaben nützlich sein, die eine schnelle Aktualisierungszeit benötigen, sowie die Anzahl der tatsächlich ausgelösten Aktionen reduzieren. In meinem aktuellen Prototyp habe ich ein Formularbearbeitungs-HOC zusammengestellt, das das aktuelle Element, das bearbeitet wird, als Requisite erhält. Es verarbeitet auch Änderungsereignisse für Formulareingaben, indem das geänderte Feld in seinem Status gespeichert und dann ein entprellter Aktionsersteller "EDIT_ITEM_ATTRIBUTE" mit den kombinierten lokalen WIP-Änderungen aufgerufen wird. Das Ergebnis ist, dass die Formularfelder sofort aktualisiert werden, da nur das Formular selbst neu gerendert wird und viel weniger Aktionen ausgelöst werden (wenn ich beispielsweise 'A' einige Sekunden lang gedrückt halte, wird nur der Wert 'AAAAAAAAAAAA' angezeigt als Aktion gesendet werden und nicht als 'A', 'AA' usw.).

Ich habe das HOC als Kernstück unter https://gist.github.com/markerikson/554cab15d83fd994dfab , wenn es jemanden interessiert.

Der Punkt ist jedenfalls, dass sowohl der Komponentenstatus als auch der Speicherstatus ihre Verwendung haben - Sie müssen nur Ihren tatsächlichen Anwendungsfall berücksichtigen.

Wenn wiederverwendbare Komponenten groß und komplex genug sind, wäre es ziemlich zukunftssicher, ihren Status in Redux zu haben, hauptsächlich zur Rückverfolgbarkeit und Wiedergabe zum Testen. Es gibt jedoch noch einige Zweifel, wie genau diese Code-Wiederverwendung aufgebaut werden sollte (Komponenten plus Aktionen plus Reduzierungen).

In unseren Anwendungen haben wir dieses Problem im Connect-ähnlichen Stil gelöst. https://github.com/Babo-Ltd/redux-state

Ich fand es selten umständlich, Zustände in Redux zu speichern. Ich mag die Kraft, die es bietet, dass ich es später mit einer anderen Komponente interagieren lassen kann, wenn ich es brauche.

Das einzige, was mir in den Sinn kommt, wo es unangenehm wäre, ist den Umgang mit Formelementen, weil es so viele davon geben kann. In diesem Fall benutze ich eine Bibliothek wie Redux-Form .

Mein Punkt ist, dass Sie einen einzelnen Statusbaum verwenden, es sei denn, dies ist umständlich, und dies nur tun, wenn dies die Dinge für Sie vereinfacht, anstatt sie zu komplizieren. Das ist die einzige Richtlinie

@gaearon Möchten Sie Ihre Erfahrungen darüber teilen, wie Sie entscheiden können, wann oder wie es als umständlich angesehen wird? Können Sie zum Beispiel einige typische Szenarien / Beispiele nennen, die Ihrer Meinung nach umständlich genug sind, wenn sie in den Anwendungsstatus Atom versetzt werden? Danke im Voraus!

@idavollen Ich kann ein paar geben:

  • Ein Dropdown-Status zum Öffnen / Schließen, andernfalls müssten Sie alle Dropdown-Komponenten in Ihrem Geschäft verfolgen
  • Wenn Sie eine Änderung von <input> entprellen, können Sie den Status verwenden, um den Wert sofort zu aktualisieren (und Sie riskieren nicht, dass andere Komponenten unnötig neu gerendert werden) und den Speicher entprellt zu aktualisieren

Grundsätzlich sollten Sie es für einen Status verwenden, der andere Komponenten nicht beeinflusst.

Ich muss eine dritte Situation berücksichtigen: Ich habe beispielsweise ein Formular (eine Reaktionscontainerkomponente mit teurer Berechnung in der Rendermethode), das aus vielen Zeilen mit vorangestelltem Kontrollkästchen und einer Schaltfläche zum Senden besteht. Wenn Sie auf die Schaltfläche "Senden" klicken, sollte das Formular die Zeilen senden, deren Kontrollkästchen aktiviert sind. Dies bedeutet, dass vorübergehende Zustände einzelner Kontrollkästchen vor dem Senden des Formulars beim Umschalten durch den Benutzer nicht wichtig sind und nicht als Komponentenstatus behandelt werden sollten und das Umschalten des Kontrollkästchens nicht dazu führen sollte render () aufgerufen werden.

Vorläufig würde ich weder den Status des Kontrollkästchens in den Status des Anwendungsstatus noch in den Status der lokalen Komponente setzen, dh in die Formreaktionskomponente, um ein unnötiges Aufrufen von render () beim Umschalten des Kontrollkästchens zu vermeiden, im Gegenteil, a Eine Instanzvariable wird bevorzugt, um die aktivierten Kontrollkästchen zu halten, ist jedoch gegen das Reaktionsmuster.

Ich frage mich, wie Sie diese Kontrollkästchenzustände in diesem Fall am besten verwalten können.

@idavollen sind diese Kontrollkästchen unkontrolliert ? Wenn nicht, rendern Sie sie trotzdem neu, sodass Sie verfolgen können, welche im Status der Komponente ausgewählt sind, und damit auswählen können, welche Teile der Daten gesendet werden sollen.

Wie schnell ist Redux im Vergleich zum Zustand der Komponenten? Sollte ich mich auf Redux für UI-Requisiten verlassen, die hinsichtlich des Timings zwischen dem tatsächlichen Ereignis und dem Rendering-Prozess wirklich sinnvoll sind? Ich habe eine komplizierte Situation, in der die Verwendung des Komponentenstatus eine Menge nicht so direkter Kommunikation erfordern würde. Jede Hilfe in dieser Angelegenheit wäre sehr dankbar.

@tiberiumaxim Nach meiner Erfahrung (ich entwickle Apps in

Es liegt an Ihnen, zu entscheiden, welcher Status in Redux verwendet wird und was für eine Komponente lokal bleibt. Möglicherweise möchten Sie http://redux.js.org/docs/faq/OrganizingState.html#organizing -state-only-redux-state und http://redux.js.org/docs/faq/Performance lesen

@deowk, danke, dass du dein Wissen über die Leistungsfrage geteilt hast. Ich dachte das Gleiche, brauchte aber eine Bestätigung.
Auch @markerikson danke für die Links, ich werde sie mir noch einmal ansehen.

Ich bin mir nicht sicher, ob jemand dies explizit erwähnt hat, aber der lokale Komponentenstatus kann auch von Redux verwaltet werden. Sie können einen Speicher direkt in Ihrem Komponentenkonstruktor erstellen. Dieser lokale Speicher enthält den Status dieser Komponente und verarbeitet Aktionen, die sich auf diese Komponente beziehen (und ihre untergeordneten Elemente, indem entweder die Funktion dispatch dieses Speichers oder Rückrufe übergeben werden, die diese Funktion dispatch aufrufen). .

Diese Architektur kann manuell implementiert werden oder eine Bibliothek wie Redux-Fraktal, Redux-UI usw. verwenden.

Oder, wie Dan betont hat, Sie können sogar einen reduzierenden Ansatz implementieren, um den Status einer Komponente zu aktualisieren! Siehe https://twitter.com/dan_abramov/status/736310245945933824

Ich möchte wissen, wo der UI-Status wie Aktivitätsindikator und modales Öffnen oder Schließen gespeichert werden soll. Verursacht die Verwendung von setState Probleme beim Unit-Test von Reaktionskomponenten?

@ akshay2604 : wieder liegt es an dir. Siehe die Links, die ich in früheren Kommentaren in diesem Thread gepostet habe. Sie können beim Testen von Komponenten definitiv setState verwenden, insbesondere wenn Sie die Enzymbibliothek zum Testen verwenden.

Lassen Sie mich meine Gedanken teilen.

Ich kategorisiere den Status in drei große Kategorien, je nachdem, wie er mit der Eingabe / Ausgabe der Anwendung zusammenhängt:

  • "Cache": Ein Status, der ein Spiegelbild persistenter Daten ist. Beispiel:
{ "todos": [{ id: 1, title: "title" }, { id: 2, title: "title" }] }
  • "Änderungen": Ein Status, der ausstehende Änderungen an persistenten Daten beschreibt. Beispiel:
{ "changeTodo": { title: "title", action: "add", done: false },
{ id: 1, title: "changed title", action: "modify", done: true }, { id: 2, action: "delete" } }
  • "Ansicht": Ein Status, der Ansichtsoptionen wie aktuelle Filterung, Sortierung usw. vermittelt. Beispiel:
{ "displayOptions": { searchTerm: "title", sort: ["title", "desc"], filter: "done=false" } }

Sie mischen nicht cache mit changes , Sie mischen nicht cache mit view , Sie mischen nicht view mit changes .

Natürlich müssen Sie diese irgendwie zusammenführen, um sie in einer einzelnen Reaktionskomponente anzuzeigen. Damit Ihr "zusammengeführtes" Objekt wird:

{ "todos": [{id: undefined, title: "title", done: false }, { id: 1, title: "changed title" }] }

Dies ist jedoch kein Status, sondern ein Ergebnis Ihrer Anwendungslogik . Sie sollten es also nirgendwo aufbewahren.
Sie können diesen zusammengeführten Status in Selektoren zwischenspeichern, Sie können ihn im Speicher zwischenspeichern, Sie können ihn in Komponenten zwischenspeichern, aber es ist kein "Status", es ist nicht wichtig, Sie können Ihre Anwendungslogikfunktion einfach auf alle 3 Statuselemente und erneut anwenden Holen Sie sich wieder einen zusammengeführten Zustand. Darum geht es beim funktionalen Ansatz.

Redux-Betreuer werden Ihnen sagen: "Hey, Sie sollten Ihre Anwendungslogik als mehrere Reduzierungen und mehrere Ereignisse implementieren, die verschiedene Teile Ihres" zusammengeführten "Objekts erstellen."
Ich denke, das ist ein falscher Ansatz. Es bedeutet, dass Sie nicht in der Lage sind, von Redux wegzukommen. Was als Werkzeug zur Verwaltung Ihres Status gedacht war, wird im Wesentlichen zu einer Implementierung Ihrer Anwendungslogik .

Hallo, ich beschäftige mich ein paar Tage mit React / Redux und verstehe die Entscheidung, ob einige Informationen zum Speichern oder Speichern im lokalen Status der Komponente heraufgestuft werden sollen.

Aber was ist, wenn eine Aktion beide gleichzeitig erfordert? Hier ist der Anwendungsfall, der sehr häufig ist:

  1. [Kontext] Der Redux-Speicher ist ein einzelnes Blatt { modelItems: myModelItems } . Es speichert (Teil / eine Projektion von) das Servermodell zwischen
  2. [Kontext] Die Ansicht besteht aus einer einzelnen intelligenten Komponente MyItemsView , die eine UI-Liste der gespeicherten / zwischengespeicherten Elemente anzeigt. Beim Mounten löst die Komponente einen Abruf von Modellelementen aus. Komponenteneingabe: myModelItems . Komponentenausgabe: ein fetchModelItems -Aktionsauslöser. Komponenteneinbauten: state.busy und state.errorId
  3. [Plan] Wenn MyItemsView fetchModelItems MyItemsView auslöst, wird eine HTTP-Anforderung an den Server gesendet, um das Modell abzurufen und im Speicher zwischenzuspeichern. Diese asynchrone Aktion hat 4 Phasen und ebenso viele Hooks: onStarted (HTTP-Anforderung steht kurz vor dem Start, Laden des Spinners beginnt in der Komponente), onEnded (HTTP-Antwort gelandet, Laden des Spinners stoppt in der Komponente , man sieht sich immer noch nicht den Antwortstatus an), onFailed (eine Fehlerbenachrichtigung wird in der Komponente angezeigt) und onSucceed (der Redux-Speicher wird aktualisiert, dann wird der darin enthaltene Modell-Cache weitergeleitet die Komponente zum Rendern)

So teilen Sie den fetchModelItems -Aktionsauslöser so auf, dass:

  • onStarted , onEnded und onFailed sind nicht im Redux Store erhältlich? Dies liegt daran, dass onStarted und onEnded vorübergehende UI-Zustände sind, die keine Interaktion mit dem Modell-Cache haben sollten. Gleiches gilt für onFailed (der Modell-Cache bleibt unverändert und die Benutzeroberfläche gibt eine Fehlerbenachrichtigung aus). MyItemsView rendert hier den UI-Status, nicht das zwischengespeicherte Modell
  • onSucceed den Redux Store? Dies liegt daran, dass es die Model-Cache-Lotterie gewonnen hat, Zugang zur Quelle der Wahrheit erhält, duscht und rehydriert und dann die frischen myModelItems in MyItemsView

Über die Implementierung in meinem aktuellen Versuch kümmert sich Redux Thunk um den Aktionsauslöser fetchModelItems . Ich habe das Gefühl, dass ich dort den Redux-Pfad gewählt habe und dass ich meine Meinung nicht mehr ändern kann, um zu sagen: "Übergebe einfach den asynchronen Erfolg an den Redux-Speicher, behalte alles andere im Status der React-Komponente".

Verwirrt rufe ich Erfolge zum Speichern ab, die an die verbundene Komponente (dh Redux-Container) weitergeleitet werden. Aber kein Ladespinner und eine miserable, von der Konsole protokollierte Fehlermeldung atm. Ich möchte weder store.ui.myItemsView.busy noch store.ui.myItemsView.errorId , sondern nur diese Informationen im Komponentenstatus abrufen.

@pascalav :
Dies ist ein Bug-Tracker, kein Support-System. Bei Fragen zur Verwendung verwenden Sie bitte Stack Overflow oder Reactiflux, wo viel mehr Leute bereit sind, Ihnen zu helfen - Sie werden wahrscheinlich schneller eine bessere Antwort erhalten. Vielen Dank!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen