Redux: Diskussionsanfrage: Redux "Boilerplate", Lernkurve, Abstraktion und Eigensinn

Erstellt am 19. März 2017  ·  108Kommentare  ·  Quelle: reduxjs/redux

Lösung: Redux Starter Kit verwenden

Aus den Ideen in diesem Thread wurde schließlich unser neues Redux Starter Kit Paket . Es enthält Dienstprogramme, um viele gängige Redux-Anwendungsfälle zu vereinfachen, einschließlich Store-Setup, Reducer-Definition, unveränderliche Update-Logik und sogar das automatische Erstellen ganzer "Slices" des Zustands, ohne Aktionsersteller oder Aktionstypen von Hand zu schreiben.

Weitere Details zu den Problemen, die das Redux Starter Kit lösen soll (und was es nicht tun wird), finden Sie im Manifest "Vision for Redux Starter Kit", das ich geschrieben habe .

Die Hauptbeschwerde, die ich über Redux sehe, ist, dass es "zu viel Boilerplate" gibt. Ich sehe auch häufig Beschwerden, dass es zu viel zu lernen gibt, zu viele andere Add-Ons, die benötigt werden, um etwas Nützliches zu tun, und zu viele Aspekte, bei denen Redux keine Meinung hat und daher keine integrierte Anleitung bietet.

Ich hatte gerade eine Diskussion mit @tannerlinsley über mehrere dieser Aspekte. Wir diskutierten die Jumpstate- Bibliothek, eine Abstraktionsschicht rund um Redux, und wie sie die Lernkurve erleichtern sollte, sowie verschiedene philosophische Meinungen darüber, was "gute" Redux-Nutzung ausmacht.

Daraus haben wir mehrere Fragen entwickelt, die ich gerne für eine breitere Diskussion aufbringen möchte:

Wichtige Punkte

Kesselplatte / Ausführlichkeit

  • Redux soll nicht die „prägnanteste Art, Dinge zu tun“ zu sein, sondern den Datenfluss offensichtlich und lesbar zu machen
  • Dokumente sind aus Gründen der Klarheit und des Lernens in einem bewusst ausführlichen Stil geschrieben und nicht speziell als "der einzig wahre Weg zum Schreiben von Redux-Code" gedacht, aber dieser Stil wurde etwas blind übernommen (oder führte manchmal zur Ablehnung von Redux).
  • Häufige Beschwerden über "Boilerplate", wie "zu viele Dateien", "Verwendung von Aktionserstellern" usw.

Abstraktionen und Lernen

  • Die Redux-Kernbibliothek selbst ist effektiv mit allen Funktionen ausgestattet, aber es gibt viele interessante Addons und Tools, die von der Community entwickelt werden
  • Es wurden verschiedene Abstraktionsbibliotheken erstellt, um "die Lernkurve zu erleichtern" oder "die Dinge mehr OOP zu machen", aber die meisten davon sind nicht wirklich "idiomatische" Redux-Nutzung
  • Die Redux-Lernkurve kann steil sein, aber sobald Sie Konzepte verstanden haben, entfällt oft der Bedarf an Abstraktionsschichten

Probleme

  • Worum geht es hauptsächlich bei den "Boilerplate"-Beschwerden?
  • Was sind die schwierigsten Aspekte von Redux für neue Lernende?
  • Was sind die "keine Meinungen"-Bereiche, die den Menschen Probleme bereiten?

Potentielle Lösungen

  • Wie würde eine idiomatische Redux-Nutzung mit "weniger Boilerplate" aussehen? Wie können wir diese Beschwerden lösen?
  • Welche möglichen Abstraktionen könnten erstellt werden, die den Lern- und Nutzungsprozess vereinfachen, ohne jedoch Redux tatsächlich zu verstecken (und würde hoffentlich einen Migrations-/Lernpfad zu "Basis" Redux bieten)?
  • Wie viel davon könnte in irgendeiner Weise mit verbesserten Dokumenten gelöst werden?

Ich möchte die Community einladen, Beschwerden, Schwachstellen und Bedenken bezüglich der Verwendung von Redux vorzubringen und hoffentlich auch Vorschläge und Ideen zur Lösung dieser Probleme bereitzustellen.

Hilfreichster Kommentar

Wenn es nach mir ginge, würde ich das gerne sehen:

  • Ein Flow/TypeScript-freundliches Subset, das einfacher zu tippen ist als Vanilla Redux.
  • Konstanten nicht so sehr betonen (machen Sie einfach die Verwendung von String-Literalen sicherer).
  • Die Unabhängigkeit von React oder anderen Ansichtsbibliotheken beibehalten, aber die Verwendung vorhandener Bindungen vereinfachen (zB Bereitstellung von mapStateToProps Implementierungen).
  • Beibehaltung der Redux-Prinzipien (serialisierbare Aktionen, Zeitreisen und Hot Reloading sollten funktionieren, Aktionsprotokoll sollte sinnvoll sein).
  • Unterstützung von Code-Splitting auf eine einfachere Weise out of the box.
  • Ermutigen Sie die Anordnung von Reduzierern mit Selektoren, und machen Sie das Zusammenschreiben weniger umständlich (denken Sie an Reduzierer-Selektor-Bundles, die einfach zu schreiben und zusammenzustellen sind).
  • Anstatt Aktionsersteller mit Reduzierern zusammenzufassen, sollten Sie die Aktionsersteller vollständig loswerden und eine Viele-zu-Viele-Zuordnung von Aktionen zu Reduzierern natürlich machen (anstatt wie die meisten Bibliotheken davor zurückschrecken).
  • Machen Sie vernünftige Leistungsstandards, damit die Speicherung über Reselect für allgemeine Anwendungsfälle „einfach funktioniert“, ohne dass Benutzer diesen Code schreiben.
  • Enthält integrierte Helfer für Indizierung, Normalisierung, Sammlungen und optimistische Aktualisierungen.
  • Mit integrierter testbarer asynchroner Flow-Unterstützung.

Natürlich zusätzlich zum Kern, obwohl es in Ordnung ist, es als offizielle Redux-Sache zu brandmarken.
Außerdem werde ich das nicht schreiben. Doch kannst du.

Alle 108 Kommentare

Ein paar Ideen:

  • offizielles Redux-Preset-Paket mit Redux, React-Redux, Redux-Thunk bereits miteinander verkabelt
  • dispatch(actionType, payload) könnte den Bedarf an Action-Erstellern reduzieren
  • eingebaute Jumpstate-Style Reducer Creators, zB createReducer({[actionType]: (state, payload) => state}, initState)

Die meisten Leute, die ich kenne, die viel Redux verwenden, entfernen sich am Ende von Redux-Thunk, da sie feststellen, dass es nicht sehr gut skaliert, und führen schließlich zu Action-Erstellern, die viel zu viel tun und lieber etwas anderes für die Verwaltung der Seite verwenden -Effekte wie Redux-Observable oder Redux-Saga.

Ich kann den Reiz darin verstehen, besonders wenn man mit Redux beginnt - aber ich bin mir nicht sicher, ob es die beste Idee wäre, es als Teil eines "Best-Practice-Boilerplate-Pakets" zu bündeln.

Daher ist dieser Teil für mich der kritischere (es werden nicht so sehr Ideen zur Lösung des Problems sein, sondern eher Einschränkungen, die zumindest für mich wichtig sind):

Redux soll nicht die „prägnanteste Art, Dinge zu tun“ zu sein, sondern den Datenfluss offensichtlich und lesbar zu machen

Eine großartige Sache an Redux ist, dass es fast mehr ein Designmuster als ein Framework ist, und der gesamte Code, den Sie sehen (abgesehen vom Store und react-redux ) ist Ihr eigener.

Wenn ich mir Jumpstate ansehe (ich wusste bisher nichts davon), ist es eine der ersten Abstraktionsschichten, die ich für Redux sehe, die gut aussieht. Sogar super! Gleichzeitig sind Sie jedoch nur ein Haar von anderen Frameworks wie MobX entfernt, und mehrere Frameworks zu haben, die dasselbe auf den Tisch bringen, ist nicht besonders nützlich. Daher ist es wichtig, sich darauf zu konzentrieren, was Redux von den anderen unterscheidet, nicht nur, wie wir Redux in einem Vakuum verbessern können (weil es in der gleichen Welt wie andere Tools lebt).

Eine andere wichtige Sache ist, dass viele Herausforderungen, die Neulinge haben, wenn sie Redux treffen, nicht Redux selbst sind, sondern JavaScript. Andere große Frameworks wie Angular abstrahieren JavaScript selbst. Das Schreiben eines Redux-Reduzierers bedeutet einfach das Anwenden von Vanille-Javascript-Designmustern, die Neulingen möglicherweise nicht vertraut sind und die Leute dazu bringen werden, stattdessen eine Blackbox zu verwenden.

Schließlich versuchen viele Boilerplate-Reduktionsbibliotheken, eine 1:1:1-Beziehung zwischen Komponenten, Reduzierern und Aktionserstellern (vielleicht nicht alle 3, aber oft 2 davon) hinzuzufügen, was Neulinge vergessen lässt, dass sie mehrere Reduzierer haben können, die eine Aktion handhaben , mehrere Komponenten, die den Status von mehreren Reduzierern verwenden, und so weiter. Das ist eine der Fragen Nr. 1, die ich bei der Arbeit und an anderen Orten beantworte, und sie ist sehr nützlich. Ein Werkzeug, das in diesem Bereich hilft, sollte dies also nicht verlieren (auch "Schalter sind eklig" ist nicht das beste Argument der Welt).

Also IMO, CTAs würden das Verknüpfen guter Vanilla-JavaScript-Ressourcen beinhalten, sowie mehr über das "Warum" entlang der "Erste Schritte"-Konzepte dokumentieren und die Dinge einfach halten. Sie können in Redux riesige Anwendungen erstellen, ohne viele neue Konzepte zu lernen. Obwohl ich selbst ein redux-beobachtbarer Typ bin, habe ich mehrere hunderttausend Zeilen Code-Apps gesehen, die Thunk ohne Probleme verwenden (und ich habe gesehen, wie winzige Apps mit Thunks ein Zugunglück machen). Es hilft sehr, sehr wenige "Kern"-Konzepte vorzustellen und zu zeigen, wie sie auf Tonnen von Konzepten angewendet werden können.

Das "alle Boilerplates müssen um jeden Preis reduziert werden" ist heutzutage ein Thema in der gesamten Software-Engineering-Community ... das ist schwieriger zu lösen.

Von Anfang an war mein Hauptanliegen bei Redux, dass ich entweder einen Code lese oder schreibe, ich zwischen N Dateien springen musste, die b/c-Logik des einzelnen UI-Teils ist über die gesamte Codebasis zwischen Aktionen, Aktionstypen und mehreren verstreut Reduzierstücke. Ich mag es wirklich, dass ich von jedem Ort in der Benutzeroberfläche aus jeden Teil des Zustandsbaums erreichen und die verschiedenen Teile des Zustands als Reaktion auf eine einzige Aktion ändern kann (Hauptgründe, warum ich Redux verwende), aber je mehr Teile von der Zustand, den ich als Reaktion auf eine einzelne Aktion ändere, desto mehr verwischt sich meine Logik. Ich kann nicht einfach lesen oder schreiben, was passiert ist, wenn der Benutzer dies oder das getan hat. Aber was ich will, lässt sich so beschreiben:

// meta code
dispatch(ACTION);

onAction = {
  ACTION: [
    // handler 1: hide spinner here,
    // handler 2: change status there,
    // handler 3: update entity
  ],
};

Am Ende kam ich auf redux-interactions + redux-tree und ich bin bis jetzt ziemlich glücklich damit.

Vorgehensweise in unserem aktuellen Projekt:

Beachten Sie, dass dies je nach Anwendungsanforderungen sehr unterschiedlich wäre :) Sobald wir Objektaktualisierungen in Echtzeit hinzufügen, würden Sagas oder Observables möglicherweise Vorteile gegenüber Thunk / Versprechen bieten

  • redux-thunk
  • Middleware versprechen
  • unser "API-Wrapper", der ein Wrapper um die Client-Feders-App ist, service(name, method, ...opts) der ein Aktionsersteller ist, bei dem die Nutzlast ein Versprechen ist, unsere API aufzurufen (dh die Versprechen-Middleware nimmt es auf und versendet es x_FULFILLED , x_PENDING und x_REJECTED ). könnte hierfür auch den Namen der Aktion überschreiben.

Wir verwenden zuerst componentDidMount() , um unsere API aufzurufen und Daten im Komponentenzustand zu speichern. Dafür verwenden wir jedoch unseren API-Wrapper, was bedeutet, dass eine Aktion immer noch gesendet wird (und von der Logger-Middleware protokolliert wird, einschließlich Meta, die Anforderungsinformationen ist), und wenn wir dies wünschen, um den Store für diese Komponente zu verwenden, brauchen wir alles, was wir brauchen to ist ein Reduzierer hinzuzufügen, der auf die Aktion lauscht. Wir beginnen damit, dass wir nur den lokalen Zustand verwenden und in Redux umwandeln, wenn auf den Zustand dieser Komponente von einer anderen Komponente zugegriffen/geändert werden muss. Abgesehen davon sehe ich den Reiz darin, Redux überall zu verwenden, da es für alles eine Papierspur bietet. Angesichts unseres aktuellen Team- und Bewerbungszeitplans ist es für uns atm einfach nicht von Vorteil.

Ich habe ein bisschen mit Redux-Saga gespielt, aber da unser kompliziertester asynchroner Ablauf das Anmelden/Abmelden ist, das funktioniert (und der Code nicht besonders kompliziert ist), kein großer Grund für einen Wechsel (aber es könnte sich zum Testen lohnen) Gründe - iterierbar + Mocks ist eine schöne Möglichkeit zum Testen). redux-observable Ich sehe den unmittelbaren Vorteil nicht, es sei denn, Observables würden selbst einen Vorteil bieten, zum Beispiel wenn Sie Ereignisse schön doppelklicken möchten.

Wir haben uns ein wenig von der Boilerplate entfernt, indem wir unsere eigenen Factory-Funktionen haben, um Reduzierer zurückzugeben, und unsere eigenen Reduzierer höherer Ordnung zusätzlich zu benutzerdefinierten Funktionen (z Aktionen zum Ändern eines Elements).

Was meiner Meinung nach getan werden muss, ist ein riesiges Tutorial, das von einer einfachen Reaction-App ausgeht, Probleme demonstriert, die bei der Kommunikation zwischen den Komponenten auftreten, dann Redux einführen und dann weitermachen,

Was auch relevant ist, ist meine Zusammenfassung, die ich für Muster erstellt habe, die in gothinkster/react-redux-realworld-example-app verwendet werden

Die meisten Leute, die ich kenne, die Redux stark verwenden, entfernen sich am Ende von Redux-Thunk, da sie feststellen, dass es nicht sehr gut skaliert

Ich verstehe, was Sie sagen, aber hier ist meine Kehrseite: Wir sehen immer mehr anekdotische Beweise dafür, dass eine große Gruppe von JS-Entwicklern noch nicht einmal _Pfeilfunktionen_ und andere grundlegende ES(6|2015)-Funktionen verwendet , aufgrund von mangelndem Verständnis, Einschüchterung usw. Von Leuten, die mit Redux beginnen möchten und die davon profitieren könnten, die _Muster_ zu lernen, die Redux einführt, zu erwarten, zuerst Observables oder Generatoren zu lernen, ist meiner Meinung nach wahrscheinlich zu viel verlangt?

Redux-Thunk ist auch in dem Sinne etwas komplex, dass Redux-Middleware im Allgemeinen Ihr Gehirn verbiegt, aber es sind zumindest nur Funktionen/Rückrufe, die leicht zu erfassen sind, wenn Sie überhaupt JS schreiben. Ich mag die Idee, ein komplettes Paket verwandter Tools für den Anfang zu haben, das über einen einzigen Download verfügbar ist, auch wenn es als "learn-redux" anstelle von "best-practice-always-redux" bezeichnet wird. Ähnlich wie die Create-React-App optimiert werden muss, wenn Sie all die Dinge lernen, die sie für Sie eingerichtet hat, könnte dies Ihre eigenen Optimierungen fördern, vielleicht zeigen, wie Sie ein einfaches Redux-Thunk-Setup in die Verwendung von Sagas usw. als eigene Form umwandeln des "Auswerfens" ...

Nur ein paar Gedanken.

Ich verstehe, was Sie sagen, aber hier ist meine Kehrseite: Wir sehen immer mehr anekdotische Beweise dafür, dass eine große Gruppe von JS-Entwicklern noch nicht einmal Pfeilfunktionen und andere grundlegende ES(6|2015)-Funktionen verwendet , aufgrund von mangelndem Verständnis, Einschüchterung usw. Von Leuten, die mit Redux beginnen möchten und die davon profitieren könnten, die von Redux eingeführten Muster zu lernen, zu erwarten, dass sie zuerst Observables oder Generatoren lernen, ist dies wahrscheinlich zu viel verlangt?

Bingo! Wir befinden uns in einer Umgebung, in der viele Leute neu bei JS sind (oder sie "kennen" JS, aber es ist nicht ihre Spezialität und sie beginnen am tiefen Ende). Besonders wenn diese Leute erfahrene Software-Ingenieure aus einem anderen Ökosystem (Java, Rails usw.) sind, werden sie schnell versuchen, die Konzepte anzuwenden, die sie kennen, bevor sie diejenigen lernen, die sie nicht kennen, und es wird nicht ganz funktionieren und sie bleiben stecken. Ich weiß jedoch nicht, wie man die Leute am besten davon überzeugen kann, sich ein tiefes Verständnis von JS anzueignen, bevor man in ein funktionales UX-Designmuster einsteigt.

Beachten Sie, dass die Redux-Dokumentation einen Abschnitt über die Reduzierung von Boilerplate für diejenigen unter Ihnen enthält, die jetzt nach etwas suchen und nicht eine ganze Bibliothek über Redux übernehmen möchten.

Wir sollten bei dieser Diskussion ein wenig vorsichtig sein und erkennen, dass dies wahrscheinlich schon viel über die Bühne gegangen ist. Das Redux-Team hat viele Dinge gehört, überlegt und abgelehnt, die hier wahrscheinlich vorgeschlagen werden. Gut möglich, dass aus dieser Diskussion nichts wird, wenn wir nur über Dinge streiten, die bereits diskutiert wurden.

Abgesehen davon halte ich es für eine großartige Idee, über Möglichkeiten zu sprechen, das Framework für alle (neue und erfahrene) zugänglicher zu machen.

Alles, was Sie zum Reduzieren von Boilerplate vorschlagen, sollte so sein, dass es möglich ist, bei Bedarf zu den Dingen unterhalb der Abstraktion zurückzukehren. Es macht keinen Spaß, eine Abstraktion zu übernehmen, nur um sie später wieder fallen zu lassen, um zu den unteren Ebenen zurückzukehren, weil Sie eine zusätzliche Sache brauchten, an die die Autoren der Abstraktion nicht gedacht haben.

Die Redux-Lernkurve kann steil sein, aber sobald Sie die Konzepte verstanden haben, ist die Notwendigkeit
Abstraktionsschichten gehen oft weg

Ich frage mich, wenn dies der Fall ist, welche Teile von Redux schlagen wir zur Verbesserung vor? Welche Teile würden Sie entfernen oder abstrahieren, die Sie nicht sofort wieder hinzufügen müssten?

Dies ist ein Diagramm des gesamten Reaktions-/Redux-Lebenszyklus, das ich vor etwa einem Jahr für einen Arbeitsvortrag erstellt habe:
React Redux Lifecycle

Es gibt einige Teile davon, aber ich kann mir nicht vorstellen, dass Redux ohne einen von ihnen so gut funktioniert. Container sind manchmal etwas nervig, aber wenn Sie sie entfernen, koppeln Sie Ihre Ansichtslogik tief mit Ihrem Datenlayout. Wenn Sie Aktionen entfernen, sind Sie im Grunde wieder MVC, was den Sinn der Verwendung von Redux an erster Stelle verfehlt. Die "Ansicht" in diesem Diagramm existiert bereits kaum, da sie nur als Funktion modelliert werden kann, die den Speicher abonniert und Reaktionskomponenten rendert.

Ich glaube nicht, dass im Gesamtframework selbst viel Boilerplate entfernt werden muss. Vielleicht beziehst du dich auf Boilerplate in den einzelnen Teilen des Frameworks wie in Action Creators, Reducern oder Containern. In diesem Fall werden die meisten dieser Dinge bereits mit den Tipps auf der oben erwähnten Seite „ Reducing Boilerplate“ behandelt. Darüber hinaus brauchen wir nichts, um es "besser" zu machen. (Hinweis: Es ist nicht so, dass ich nicht offen dafür wäre, etwas hinzuzufügen, um die Dinge zu verbessern, ich sehe es nur noch nicht.)

Vielleicht ist dies nicht so sehr ein Problem mit der Reduzierung von Boilerplates, sondern ein Problem der Verbesserung der Redux-Erziehung. Wenn das Framework für Anfänger schwer zu erlernen ist, müssen wir möglicherweise die Redux-Dokumentation verbessern und zugänglicher machen. Vielleicht müssen einige der reduzierenden Boilerplate-Tipps in den Dokumenten aggressiver beworben werden.

Die Reduzierung der erforderlichen Schritte (Boilerplate) löst das Problem nicht immer. Um meinen Punkt von Anfang an zu betonen, möchten Sie keine Abstraktion schreiben, die weggeworfen wird, weil Sie nicht daran gedacht haben, wie die Leute sie verwenden müssen.

Bisher einige gute Diskussionen. Lassen Sie mich ein paar kurze Beispiele für häufige Beschwerden im Zusammenhang mit "Boilerplate" herauswerfen, die ich sehe:

  • "Warum muss ich 'Aktionsersteller'-Funktionen schreiben, nur um ein Objekt sofort zurückzugeben?"
  • "Ich muss SOOO viele Dateien anfassen, nur um eine einfache neue Funktion hinzuzufügen! Außerdem wiederhole ich immer wieder dieselben Namen für Konstanten und Funktionsnamen und..."
  • "Warum brauche ich diese 'Middleware'-Dinge nur, um einen AJAX-Anruf zu tätigen?"
  • "Warum muss ich für alles switch-Anweisungen verwenden?"
  • "Warum brauche ich dieses dispatch Ding? Warum muss ich all diese Funktionen einpacken, damit sie funktionieren?"

Und einige konkrete Beispiele für diese Art von Kommentaren:

Und um sofort einige Antworten auf diese "Boilerplate"-Bedenken zu verwerfen: Von diesen fünf aufgeführten Kategorien ist nur "Verwendung von dispatch " tatsächlich _erforderlich_. Für den Rest:

  • Sie _müssen_ keine Action Creators verwenden, aber es ist eine gute Praxis für Konsistenz (gemäß meinem Beitrag Idiomatic Redux: Warum Action Creators verwenden? )
  • Sie _müssen_ nicht vollständig separate Dateien für Aktionsersteller, Aktionskonstanten und Reduzierer haben. Das "Enten"-Muster ist ein beliebter Ansatz, um all diese in einer Datei zusammenzufassen. Das hat den Nachteil, dass die Möglichkeit, mehrere Reduzierer auf eine Aktion zu hören, "versteckt" wird. Redux ist es letztendlich egal, wie Ihre Dateistruktur aussieht.
  • Sie _können_ asynchrone Arbeiten außerhalb von Redux vollständig ausführen, wie in einer Komponente. Aber gemäß Dans Beschreibung unter Warum brauchen wir Middleware für den asynchronen Fluss in Redux? .
  • Sie müssen definitiv _nicht_ switch-Anweisungen in Reducern verwenden, sie sind nur die "offensichtlichste" Methode, mehrere Werte für eine bestimmte Variable zu handhaben. Nachschlagetabellen, if/else-Anweisungen und alles andere, was Sie wollen, sind in Ordnung (gemäß FAQ: Muss ich switch-Anweisungen verwenden? )
  • Sie _müssen_ tatsächlich store.dispatch() aufrufen, damit etwas Nützliches passiert - das ist eine grundlegende Designentscheidung von Redux. Durch das Binden von Aktionserstellern ist es möglich, sie an nicht verbundene untergeordnete Komponenten weiterzugeben und sie trotzdem bei jedem Aufruf der Funktion ausführen zu lassen.

Insgesamt gibt es also fast nichts von diesen "Boilerplate" -Anliegen, das _erforderlich_ ist. Es ist eine Kombination aus Beispielen aus der Dokumentation und "guten Programmierpraktiken" wie der Deduplizierung von Code und der Trennung von Bedenken.

Die von @markerikson aufgeworfenen Fragen finde ich wirklich fair und habe sie mir in der Vergangenheit auch schon einmal gestellt.

Redux ist gewissermaßen eine "Low-Level"-Bibliothek für die Datenmodellierung. Wie jede solche Low-Level-Bibliothek enthüllt sie viele Dinge, die Sie leicht abstrahieren könnten, um die meisten Fälle zu berücksichtigen. Ich denke, der Grund, warum @gaearon das ursprünglich nicht getan hat, ist, dass er die Bibliothek so klein und flexibel wie möglich halten wollte. Dank dieser Entscheidung können wir viele verschiedene Dinge auf Redux aufbauen, ohne alles im Redux-Kern haben zu müssen.

Vielleicht sollten wir bedenken, dass der richtige Weg darin besteht, eine gute Bibliothek auf Redux (wie Jumpstate?) zu entwickeln und zu stabilisieren. Wir beginnen damit, den Leuten das beizubringen, und geben ihnen dann einen einfachen Weg, Redux bei Bedarf direkt zu verwenden.

Ich glaube nicht, dass Redux viel mehr in seiner Kerncodebasis braucht und ich sehe keinen Teil davon, der dauerhaft abstrahiert werden muss. (Wenn ja, lass es mich wissen :smile:) Meiner Meinung nach gibt es nicht viel zu gewinnen, indem man Dinge aus dem Redux-Kern hinzufügt oder entfernt.

Die Verbesserung einer Bibliothek bis zu dem Punkt, an dem sie stabil und flexibel genug ist, damit jeder sie verwenden kann, ist wahrscheinlich eine bessere Option. Wie Sie sagten, wird nicht viel von der "Boilerplate" benötigt , also lasst uns sie in einer Bibliothek über Redux loswerden, anstatt Redux selbst zu modifizieren.

Ein Beispiel dafür, wie dies in einer anderen Community geschieht, ist die Programmiersprache Rust. Es gibt eine nicht blockierende IO-Bibliothek für die Programmiersprache Rust namens "mio" . Es konzentriert sich darauf, klein und niedrig zu sein, genau wie Redux. Die Sache ist, dass so ziemlich niemand es direkt verwendet, weil das wirklich hart und voller Boilerplate wäre. Fast jeder verwendet eine andere Bibliothek namens tokio, die auf mio aufbaut und sie äußerst benutzerfreundlich und ergonomisch macht. Auf diese Weise kann jeder, der die Klempnerarbeit von mio benötigt, diese direkt verwenden, aber jeder, der nur schnell etwas machen möchte, kann tokio verwenden.

Wir sollten ein ähnliches Modell annehmen.

Um ein paar Kommentare von @sunjay zu erweitern:

Es gab kürzlich einen Kommentar in #775, der meiner Meinung nach die Dinge gut einfängt:

Redux ist ein generisches Framework, das eine Balance aus gerade genug Struktur und gerade genug Flexibilität bietet. Als solches bietet es Entwicklern eine Plattform, um ein benutzerdefiniertes Zustandsmanagement für ihre Anwendungsfälle zu erstellen und gleichzeitig Dinge wie den grafischen Debugger oder die Middleware wiederzuverwenden.

Also ja, Redux ist in vielerlei Hinsicht "nur ein Muster". Die Kernbibliothek ist wirklich vollständig - die einzigen wirklichen halbgeplanten Änderungen sind Dinge wie die vorgeschlagene Umstrukturierung des Enhancers ( #1702, #2214) und möglicherweise eine Flexibilisierung von combineReducers ( #1768 , #1792 usw.). ).

Fast zwei Jahre sind seit der Erstellung von Redux vergangen, und wir haben jetzt eine ziemlich gute Vorstellung davon, wie die Leute es verwenden. Als Beispiel hat @jimbolla in #2214 eine Liste aller bekannten Shop-Enhancer zusammengestellt und kategorisiert, wie sie funktionieren und wofür sie verwendet werden. Ich bin immer noch ein absoluter Fan der Einfachheit und Flexibilität von Redux, aber ich würde gerne einige immer noch idiomatische Abstraktionen zusätzlich zu Redux sehen, die den allgemeinen Gebrauch vereinfachen und Probleme für die Leute lösen würden.

Ein weiterer Satz halbbezogener Themen und etwas, an dem ich ein ausgeprägtes persönliches Interesse habe, sind die Ideen von "gekapselte Logik/Komponenten" (gemäß "Scalable Frontend with Elm/Redux" Playground ) und "Plug -and-play Redux setup" (wie in Experimenten wie https://github.com/brianneisler/duxtape/issues/1 , https://github.com/jcoreio/redux-features/issues/7 usw. Das globale Status- und App-Setup ist für einige Anwendungsfälle großartig, für andere jedoch nicht so sehr.

Als interessanter Aspekt hat @toranb großartige Arbeit geleistet und einen Ember-Wrapper für Redux unter https://github.com/ember-redux/ember-redux erstellt . Die Ember-Welt steht _wirklich_ auf "Konvention über Konfiguration", und so richtet ember-redux eine vernünftige Standardspeicherkonfiguration ein, einschließlich redux-thunk und so weiter. Ein solcher Ansatz könnte hilfreich sein.

Also ja, ich werfe hier eine ganze Reihe verschiedener Gedanken aus, aber sie hängen auf verschiedene Weise zusammen. Insgesamt möchte ich die Barrieren für das Erlernen und Verwenden von Redux senken und übergreifende Anwendungsfälle ermöglichen.

Redux ist eine allgemeine API, nicht spezialisiert. Dies macht es ausführlicher und deckt gleichzeitig mehr Fälle ab. Seine Stärke liegt in komplexer Software, während jedes neue oder einfache Projekt den Rahmen der Notwendigkeit sprengt.

Sie können jedoch Spezialisierungen auf allgemeinen APIs aufbauen. Zum Beispiel verwende ich https://github.com/acdlite/redux-actions, was die Boilerplate für allgemeine Fälle reduziert. Ich nutze immer noch die volle Leistung von Redux und diese Schnittstelle würde für meine Bedürfnisse nicht ausreichen.

Das andere Problem besteht darin, dass neue Leute, die den Schmerz unglaublich komplizierter Anwendungen noch nicht erlebt haben, sich fragen, was der Sinn ist. Nun, für sie sollten sie wahrscheinlich nicht einmal Redux verwenden, bis sie diesen Schmerz erfahren haben, aber Dans Eierkopf-Serie kann sie ziemlich leicht über diesen Punkt hinausbringen.

https://egghead.io/courses/getting-started-with-redux
https://egghead.io/series/building-react-applications-with-idiomatic-redux

Referenz: Das Abstraktionsspektrum: https://www.youtube.com/watch?v=mVVNJKv9esE

Wie bereits erwähnt - redux-actions ist ziemlich gut darin, einige Boilerplates zu entfernen, das Entfernen von Konstanten aus der Gleichung durch Anhängen von .toString ist eine wirklich nette Idee, die ich mag, aber ich schreibe diese Logik lieber selbst, als redux-actions zu verwenden

Imho sollte es einen eingebauten Mechanismus ( subscribe 's Callback-Argument?) geben, um den abgesetzten Actions-Stream zu beobachten (ich weiß, dass dies in einer Middleware möglich ist, aber das schränkt den Anwendungsfall stark ein, da er nicht verwendet werden kann außen, dh nach Komponenten oder connect )

Ich bringe anderen oft Redux bei und es kann aus den folgenden Gründen ziemlich entmutigend sein:

  • Viele bewegliche Teile: Store, State, Reducer, Action Creator, Actions, Async Actions, Middleware, Connected Components
  • Bibliotheken. Für eine einfache App, die mit einer REST-API kommuniziert, benötigen Sie: Redux, React-Redux, Redux-Thunk (oder andere) + zusätzliche Bibliotheken, wenn Sie Dinge testen möchten
  • Anzahl der Stellen, an denen Sie Code einfügen müssen (siehe _bewegte Teile_)

Ich denke, Redux ist eine großartige Bibliothek, die an sich total Sinn macht, und ich denke, sie hat großartige Abstraktionen und ist bei richtiger Verwendung super skalierbar. Ich schätze auch, dass Redux mit jeder UI-Bibliothek verwendet werden kann, denke aber, dass es in den meisten Fällen mit Reagieren verwendet wird.

Im Allgemeinen glaube ich, dass eine Menge Frustration von den vielen beweglichen Teilen herrührt.

Hier sind einige Gedanken, die ich hatte. All dies kann auf Redux aufgebaut werden, damit es so bleiben kann, wie es ist.

  • Stellen Sie eine Bibliothek wie React Redux bereit, die zusätzlich eine integrierte Unterstützung für asynchrone Aktionen bietet.
  • Viele asynchrone Aktionen kommunizieren mit einer REST-API, also stellen Sie dafür eine idiomatische Middleware bereit
  • Schreiben Sie intelligente Komponenten als tatsächliche Komponenten, anstatt Connect zu verwenden. Sie können dann dumme Komponenten in ihrer render Methode rendern
  • Verschreiben Sie ein skalierbares Dateilayout für _Containerkomponenten_, _intelligente Komponenten_, _dumme Komponenten_, _Aktionsersteller_ und _Reduzierer_.
  • Geben Sie ein _redux-cli_ an, um Code zu generieren, zB redux action loadUsers
  • Standardisieren Sie auf einer asynchronen Ebene wie Redux-Saga oder Redux-Observable und fügen Sie sie in die Dokumentation ein (Es wäre schön, _eine_ Anlaufstelle für die meisten Redux-Angelegenheiten zu haben)
  • standardmäßig auf erweiterte Sprachfunktionen (z. B. Dekoratoren (@connect)) oder TypeScript, um die Dinge insbesondere in mapStateToProps und mapDispatchToProps weniger ausführlich zu machen (mobx erfordert Dekoratoren und die Syntax ist unkompliziert)

T

Zugegeben, redux-actions ist ein gutes Beispiel für einige einfache Abstraktionen, die Boilerplate entfernen.

Lassen Sie mich dies fragen: Create-React-App enthält das Paket react-scripts , das vorgefertigte Babel- und Webpack-Konfigurationen enthält und eine Reihe von sinnvollen Standardeinstellungen enthält. Wie könnte ein entsprechendes redux-scripts Paket aussehen?

Ich stimme einigen der anderen (negativen) Kommentare zu redux-thunk . Ich würde es Anfängern nicht empfehlen (ich würde es wahrscheinlich überhaupt nicht mehr empfehlen):

  1. Es scheint wie Magie zu beginnen.
  2. Es nimmt nicht wirklich viel Boiler-Plate weg. Bei einem komplexeren asynchronen Prozess ist es nur ein kleiner Teil des Codes, dispatch von Requisiten holen und übergeben zu müssen.
  3. Dies führt zu Aktionserstellern, die Sie nicht zu größeren Workflows zusammenstellen können.
  4. Ein letzter Punkt, den ich nicht sehr gut artikulieren kann, macht den Redux-Stil eher zu einem Framework als zu einer Bibliothek: Sie verlassen sich darauf, dass das Framework Ihren Code aufruft, anstatt dass Sie die Bibliothek aufrufen.

Wir haben es ziemlich häufig in einer React-Native-Anwendung verwendet, und es war hauptsächlich nützlich, aber wir hatten Probleme beim Zusammenstellen von Aktionen (denken Sie an "Profil nach erfolgreicher Anmeldung laden"), da die Ersteller von Redux-Thunk-Aktionen effektiv void (dh nichts wie ein Versprechen, das für die Sequenzierung der nächsten Aktion verwendet werden soll).

Es neigt dazu, die Leute zu ermutigen, zu denken, dass "der einzige Weg, etwas zu tun, darin besteht, dispatch sofort vom React-Ereignishandler/Callback aus zu machen". Und da wir wurden mit connect von react-redux und stark auf schiefen mapDispatchToProps , neigten wir vergessen , dass unsere Event - Handler einfach nur Funktionen sein könnten.

(Beachten Sie, dass die obige Anwendung hauptsächlich Anfang letzten Jahres geschrieben wurde und wir nicht wirklich mit den Ereignissen im größeren Redux-Ökosystem Schritt gehalten haben, daher kann sie veraltet sein).

@bodhi : Ohne _zu_ viel von einer Tangente zu gehen, würde ich einigen dieser Schlussfolgerungen nicht zustimmen. redux-thunk ist 11 Zeilen lang und es gibt einige nette Erklärungen wie "Was ist ein Thunk?" . Thunks _sind_ bis zu einem gewissen Grad zusammensetzbar, und ich denke, es ist im Allgemeinen einfacher, jemandem zu sagen: "Schreibe diese paar Zeilen von Funktionsdeklarationen, dann mache deine AJAX-Aufrufe und so hier". Ich habe einen Beitrag, der einige der verschiedenen Kompromisse von Thunks (und bis zu einem gewissen Grad von Sagas) bei Idiomatic Redux diskutiert: Gedanken zu Thunks, Sagas, Abstraktion und Wiederverwendbarkeit .

Ich stimme zu, dass es in einer hypothetischen Abstraktionsschicht _irgendwie_ "gesegnete" oder "eingebaute" Möglichkeiten geben müsste, mit Nebenwirkungen umzugehen. Sagas und Observables sind beide großartig, _wenn_ Sie verstehen, wie man sie benutzt. Ich weiß nur nicht, ob sie angemessen sind, da ein potenzielles Ziel hier darin besteht, einen einfacheren Weg zum Erlernen und Verwenden von Redux zu bieten.

Ich finde, dass es bei der Verwendung von redux-thunk nicht nur darum geht, etwas asynchron zu tun, sondern auch etwas zu tun, das vom aktuellen Zustand abhängt. Sehr saubere, einfache Benutzeroberfläche und fördert die Verwendung von Action-Creators.

Bodhi: Vielleicht etwas abseits des Themas, aber ich dachte nur, vielleicht ist es erwähnenswert, dass Dispatch nicht void zurückgibt, sondern das Ergebnis Ihrer inneren Funktion. Wenn Sie also beispielsweise ein Versprechen zurückgeben, können Sie Aktionen problemlos aneinanderreihen. Siehe Abschnitt zur Zusammensetzung in der Readme:
https://github.com/gaearon/redux-thunk/blob/master/README.md

Ansonsten möchte ich mich bei der Community für diese offene Diskussion bedanken, sehr interessant, die Gedanken und Ideen aller zu hören.
Ich persönlich bleibe bisher bei Thunks, versuche aber klar zu trennen, "was passiert ist" und "wie sollte sich der Zustand ändern". Ich sehe in unserem Code einige Fälle, in denen wir diesen Fehler machen (Verwendung von Aktionen, um den Reduzierern mitzuteilen, was sie tun sollen, anstatt dass Reduzierer nur darauf reagieren, was passiert ist), also wäre es schön, eine Bibliothek zu sehen, die das irgendwie schwieriger macht tun (noch nicht auf Sagen verkauft).

Am 19. März 2017 um 23:48 schrieb Bodhi [email protected] :

Ich stimme einigen der anderen (negativen) Kommentare zu Redux-Thunk zu. Ich würde es Anfängern nicht empfehlen (ich würde es wahrscheinlich überhaupt nicht mehr empfehlen):

Es scheint wie Magie zu beginnen.
Es nimmt nicht wirklich viel Boiler-Plate weg. Bei einem komplexeren asynchronen Prozess stellt sich heraus, dass es nur ein kleiner Teil des Codes ist, den Dispatch von Requisiten abrufen und übergeben zu müssen.
Dies führt zu Aktionserstellern, die Sie nicht zu größeren Workflows zusammenstellen können.
Ein letzter Punkt, den ich nicht sehr gut artikulieren kann, macht den Redux-Stil eher zu einem Framework als zu einer Bibliothek: Sie verlassen sich darauf, dass das Framework Ihren Code aufruft, anstatt dass Sie die Bibliothek aufrufen.
Wir haben es ziemlich häufig in einer React-Native-Anwendung verwendet, und es war meistens nützlich, aber wir hatten Probleme beim Zusammenstellen von Aktionen (denken Sie an "Profil nach erfolgreicher Anmeldung laden"), da die Ersteller von Redux-Thunk-Aktionen effektiv void zurückgeben (dh mit nichts wie ein Versprechen, um die nächste Aktion zu sequenzieren).

Es neigt dazu, die Leute zu ermutigen, zu denken, dass "der einzige Weg, etwas zu tun, darin besteht, sofort vom React-Ereignishandler/Callback zu senden". Und da wir Connect von React-Redux verwendeten und uns stark auf mapDispatchToProps stützten, neigten wir dazu zu vergessen, dass unsere Event-Handler nur einfache Funktionen sein konnten.

(Beachten Sie, dass die obige Anwendung hauptsächlich Anfang letzten Jahres geschrieben wurde und wir nicht wirklich mit den Ereignissen im größeren Redux-Ökosystem Schritt gehalten haben, daher kann sie veraltet sein).


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

(tut mir leid, die Tangente fortzusetzen, aber...)

Es ist erwähnenswert, dass Dispatch nicht void zurückgibt, sondern das Ergebnis Ihrer inneren Funktion.

Huch, großartig! Ich glaube, ich habe mir die Dokumentation nie zu genau angeschaut, bevor ich versucht habe, einen anderen Weg zu finden, um unsere Probleme zu lösen.

Das Wertvollste, was Redux so viel einfacher gemacht hat, ist die Behandlung von Aktionen als Ereignisse und nicht als Befehle . Dies eliminiert den Kampf, zu entscheiden, wie man Aktionen gestaltet und was man in sie einfügt.

Komponenten müssen nicht wissen, wie sich die Benutzerinteraktion auf den Zustand auswirken soll, sie teilen der Außenwelt nur mit, was in ihnen passiert ist, zB "Button X angeklickt" . Wenn Sie Aktionen als Befehle verwenden, führen Sie effektiv eine bidirektionale Bindung zwischen Komponente und Zustand ein.

Reduzierer sind nicht an Komponenten gebunden, sie repräsentieren den Anwendungszustand und nicht den Komponentenzustand , und sie sind die einzige Partei, die tatsächlich weiß, wie sich der Zustand ändert. Es gibt keine kognitive Barriere bei der Handhabung einer einzelnen Aktion in mehreren Reduzierern, da eine Aktion keine Aussage ist, "was mit dem Zustand zu tun ist" .

Dadurch wird auch der Fall beseitigt, dass mehrere Aktionen synchron verteilt werden.

Jeder Fall für das Versenden einer einzelnen Aktion von mehreren Orten entfällt ebenfalls. Sie können Aktionsersteller in der Nähe der Komponente halten, wodurch Sie die Komponente, die die Aktion ausgelöst hat, leicht aufspüren können.

Wenn Sie sich das Aktionsprotokoll in DevTools ansehen, können Sie einen vollständigen Verlauf dessen sehen, was in Ihrer App

Dieser Pull-basierte Ansatz macht den Datenfluss wirklich unidirektional und lässt sich auf natürliche Weise mit Nebeneffekt-Verwaltungsbibliotheken wie redux-saga oder redux-observable .

@aikoven Obwohl ich dem voll und ganz zustimme (es gab in der Vergangenheit definitiv viele Diskussionen zum Vergleich von Redux mit Event-Sourcing), was macht man mit Dingen wie FETCH_USER , die sehr häufig zu sehen sind (und etwas, das muss getan werden). Das scheint eher "befehlsartig" als "ereignisartig" zu sein.

@blocka Es gibt immer ein Ereignis, das zu einer Netzwerkanfrage führt. Die Anfrage selbst kann in FETCH_USER_STARTED und FETCH_USER_DONE / FETCH_USER_FAILED Aktionen verpackt werden, wodurch das Anfrageergebnis im Status landet.

👍 für redux-actions

Was ich neben der Reduzierung von Boilerplate auch daran mag, ist, dass es sich einfach wie eine sehr natürliche Erweiterung von Redux anfühlt. Für so etwas wie jumpstate ich das Gefühl, dass die Implementierung etwas weiter weg ist, und jetzt muss ich irgendwie zwei Dinge lernen anstatt eines.

Mein Punkt ist also, dass sich alle Plugins, die wir hinzufügen, um die Boilerplate zu reduzieren, sehr wie die Arbeit mit Redux anfühlen sollten, wenn auch mit einer weniger ausführlichen API.

Ein Großteil der Boilerplate ist die gleiche Boilerplate, die Sie in jeder Umgebung haben. Wenn Sie auf Duplizierung stoßen, lösen wir sie normalerweise mit einer benutzerdefinierten Abstraktion. Diese Abstraktionen sind außerhalb Ihres aktuellen Projekts sehr oft nicht nützlich, und eine "Wunderwaffe" kann einfach nicht existieren. Die Anforderungen jedes Projekts sind unterschiedlich.

Das gleiche mit Redux. Wenn es Ihnen gut geht, dass Sie eine FETCH_X_STARTED Aktion und einen fetchX() Aktionsersteller und einen Reduzierer benötigen, um damit umzugehen usw., können Sie sich gerne Ihre eigene Abstraktion ausdenken!

Redux für Boilerplate zu beschuldigen ist wie das Kopieren und Einfügen Ihres gesamten Codes und dann das Beschuldigen von Javascript für zu viel Boilerplate.

Ich finde, dass es bei der Verwendung von Redux-Thunk nicht nur darum geht, etwas asynchron zu tun, sondern auch etwas zu tun, das vom aktuellen Zustand abhängt. Sehr saubere, einfache Benutzeroberfläche und fördert die Verwendung von Action-Creators.

Die Verwendung von Redux-Thunk für synchronen Code ist keine gute Idee und sollte in der Dokumentation erwähnt werden.
Wenn Sie viele Funktionen zusammen komponieren, sind Sie sich nicht sicher, ob der Dispatch-Flow nicht auftragsabhängig ist, so dass es schwieriger zu argumentieren und zu testen ist.

Es scheint mir besser zu sein, reine Aktionsersteller zu haben und für komplexere Zustandsänderungen einfach Aktions-Batching zu verwenden. Auf diese Weise haben Sie nur reine Funktionen zum Testen.

Zum besseren Verständnis empfehle ich diesen Blogbeitrag: http://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/

@Machiaweliczny danke für den Artikel. Ich denke, die Frage an mich ist eher, wo Sie Ihre Geschäftslogik platzieren (wie in https://medium.com/@jeffbski/where -do-i-put-my-business-logic-in-a- React-Redux-Application-9253ef91ce1#.3ce3hk7y0). Sie sagen nicht, dass Ihr Dispatch-Flow (Thunk, Epic, Saga, was auch immer) niemals Zugriff auf den aktuellen Anwendungsstatus haben sollte, oder?

@dfbaskin

Denken Sie daran, dass Redux keine domänengesteuerte Entwicklung ist. "Geschäftslogik" ist hier ein viel unscharfes Anliegen, und es ist eher "welche Funktionssignatur des Konzepts am besten zu der Logik passt, die ich zu implementieren versuche". Ihre "Geschäftslogik" wird auf Selektoren, Reduzierer, Aktionsersteller und "Orchestratoren" (haben wir schon ein besseres Wort dafür?) verteilt, je nachdem, was Sie brauchen.

Der Reduzierer, der (state, action) => state ist, ist dort, wo "Logik, die vom Zustand abhängt" im Allgemeinen sein sollte. Und tatsächlich, in Dingen wie der Elm-Architektur befindet sich all diese Logik in der Funktion "Aktualisieren" (das Äquivalent zu unserem Reducer).

Leider kann der Reducer in Redux immer nur synchrone Logik verarbeiten. Eine asynchrone "Geschäftslogik", die vom Zustand abhängt, muss sie also entweder per Dispatch von der Komponente abrufen (wenn die Komponente diese Informationen enthält, was nicht immer der Fall ist) oder über Ihr Orchestrator-Konzept Ihrer Wahl (Thunk, Sagas, Epic). die dafür Zugang zum Staat haben.

Ohne die Begrenzung des Reduzierers wäre sie nicht erforderlich. Sie sehen es tatsächlich, wenn Leute Redux-Saga oder Redux-Observable verwenden: Ihre Aktionen / Aktionsersteller werden normalerweise fast trivial (in den meisten Fällen plus oder minus etwas Normalisierung oder Formatierung), und die Saga / Epic sind fast "alternative Reduzierer". , darauf haben Sie jetzt ein anderes Ding, das Zugriff auf Aktion hat und ein "Ding" ausgibt und zurückgibt, und die Komplexität des eigentlichen Reduzierers wird dadurch verringert. Reduzierer und Orchestratoren sind sehr eng verwandt (manchmal zu eng, und es ist nicht toll, 2 Konstrukte zu haben, die die Hälfte der Zeit austauschbar sind ... aber es ist das, was wir haben, wir könnten es genauso gut genießen)

@Machiaweliczny : Als Autor dieses Beitrags zu "Thunks on Thunks" kann ich Ihnen versichern, dass "Verwendung von Thunks für synchrone Arbeit vermeiden" das _Gegenteil_ von dem ist, was ich zu sagen versuchte :)

Weitere gute Diskussionen, aber wir fangen an, ein bisschen vom Thema abzuweichen. (Ist das ein Fahrradschuppen, den ich da drüben sehe? :) )

Lassen Sie mich auf die ursprünglichen Fragen zurückkommen:

  • Wie würde eine idiomatische Redux-Nutzung mit "weniger Boilerplate" aussehen? Wie können wir diese Beschwerden lösen?
  • Welche möglichen Abstraktionen könnten erstellt werden, die den Lern- und Nutzungsprozess vereinfachen, ohne jedoch Redux tatsächlich zu verstecken (und würde hoffentlich einen Migrations-/Lernpfad zu "Basis" Redux bieten)?
  • Wie viel davon könnte in irgendeiner Weise mit verbesserten Dokumenten gelöst werden?

Welche konkreten Schritte können wir umsetzen, um diesen zu begegnen?

Im Bereich unumstrittener, umsetzbarer, kurzfristiger Schritte würde ich sagen:

1) Die Konfiguration des Stores vereinfachen (vielleicht mit einer Standardkonfiguration? Ich weiß nicht, ob dies immer noch der Fall ist, aber Elm hatte früher einen "Starter-App"-Typ und einen normalen App-Typ. Die Starter-App wurde verwendet für einfache Apps und in Schulungsmaterialien, um den 90%-Fall abzudecken, wenn Leute gerade lernen.Ich gebe zu, dass ich den Redux Store bis heute nicht mit grundlegenden Middlewares (Devtools, Thunks) konfigurieren kann, ohne im Dokument nach den Signaturen zu suchen. Ich glaube nicht, dass viele Leute behaupten würden, dass Neulinge wissen müssen, wie man die Middleware eines Geschäfts konfiguriert, um die Redux-Kernkonzepte zu erlernen.

2) Dies kann bereits der Fall sein, stellen Sie sicher, dass das Hinzufügen von Redux mit dem obigen "Starter-Store" zu create-react-app so einfach wie möglich ist, damit ein Neuling in 2 Minuten eine lauffähige Redux-App haben kann.

Ich denke, das würde uns sehr, sehr weit bringen.

Bearbeiten: Mit Starter-App meine ich keine App-Boilerplate, sondern einen "createStore", der nicht konfiguriert werden kann, aber vernünftige Standardeinstellungen hat, die die Leute einfach importieren und damit erledigen können. Dann können sie einfach zum "echten" createStore übergehen, wenn sie ihm entwachsen sind.

Das klingt nach einem ziemlich fantastischen Konzept.

Am Mo, 20. März 2017 um 10:02 Uhr Francois Ward [email protected]
schrieb:

Im Bereich unumstrittener, umsetzbarer, kurzfristiger Schritte würde ich sagen:

1.

Machen Sie den Store einfacher zu konfigurieren (vielleicht mit einem Standard
Aufbau? Ich weiß nicht, ob das noch so ist, aber Elm hatte das mal
einen "Starter-App"-Typ und einen normalen App-Typ. Die Starter-App wurde verwendet für
einfache Apps und in Schulungsmaterialien, um den 90%-Fall abzudecken, wenn Menschen es sind
gerade lernen. Ich gebe bis heute zu, dass ich den Redux Store nicht konfigurieren kann
mit grundlegenden Middlewares (Devtools, Thunks) ohne das Dokument nachzuschlagen
die Unterschriften. Ich glaube nicht, dass viele Leute behaupten würden, dass Neuankömmlinge brauchen
um zu wissen, wie man die Middleware eines Shops konfiguriert, um den Redux-Kern zu lernen
Konzepte.
2.

Dies kann bereits der Fall sein, stellen Sie sicher, dass Sie Redux mit dem oben genannten hinzufügen
"Starter Store" zu erstellen-reagieren-App ist so einfach wie möglich, also ein Neuling
kann in 2 Minuten eine betriebsbereite Redux-App haben.

Ich denke, das würde uns sehr, sehr weit bringen.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/reactjs/redux/issues/2295#issuecomment-287806663 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AFUmCQYkUwjkCugevDBWC8TOu0HhWJTnks5rnqMWgaJpZM4MhnVF
.

Unsere Module verwenden combineReducers so dass jedes State-Slice in einem Modul einen dedizierten Reduzierer dafür hat (ich glaube, dieser Ansatz wird im Abschnitt Strukturierende Reduzierer der Dokumente, auch bekannt als "Slice-Reduzierer", beschrieben). Dies erleichtert die Argumentation, da die switch-Anweisungen viel kleiner sind. Es ermöglichte auch, dass in unserer Codebasis gemeinsame Reduzierer auftauchen. Die einfachsten Reduzierer waren mit Ausnahme ihrer Aktionstypen in allen Modulen identisch, sodass wir die Boilerplate durch Hilfsfunktionen (Reduziererfabriken?) reduzieren konnten, die diese Reduzierer für uns nach Aktionstyp herstellt:

const { makeIndicator, makePayloadAssignor } from '../shared/reducers';

const searchModule = combineReducers({
  searching: makeIndicator(c.SEARCH),
  results: makePayloadAssignor(c.SEARCH_RESPONSE, [])
});

Vielleicht wäre die Identifizierung häufigerer Slice-Reducer wie dieser ein guter Weg, um die Boilerplate-Probleme auszuräumen, da sie als primitive Bausteine ​​​​für unsere Reducer dienen könnten.

Dies ist grundlegendes Javascript-Refactoring. Wie ich schon sagte... "javascript" hat ein
viel "Boilerplate", bis Sie Dinge wie Abstraktion auf Ihren Code anwenden.

Redux ist nur Javascript. Daran ist nichts Magisches.

Am Mo, 20.03.2017 um 12:44 Uhr, Markus Coetzee [email protected]
schrieb:

Unsere Module verwenden kombinierenReducer, damit jeder Zustands-Slice in a
Modul hat einen speziellen Reduzierer dafür (ich glaube, dieser Ansatz ist skizziert)
im Abschnitt Strukturierungsreduzierer der Dokumente, auch bekannt als "slice ."
Reduzierstücke"). Dies erleichtert das Nachdenken, da der Schalter
Aussagen sind viel kleiner. Es ermöglichte auch die Entstehung gemeinsamer Reduzierstücke
in unserer Codebasis. Die einfachsten Reduzierstücke waren in allen Modulen identisch
abgesehen von ihren Aktionstypen, also konnten wir Boilerplate um . reduzieren
mit Hilfsfunktionen (Reduzierwerksfabriken?), die diese Reduzierstücke für
uns nach Aktionstyp:

const { makeIndicator, makePayloadAssignor } from '../shared/reducers';
const searchModule = kombinierenReducers({
Suche: makeIndicator(c.SEARCH),
Ergebnisse: makePayloadAssignor(c.SEARCH_RESPONSE, [])
});

Vielleicht wäre es gut, gängigere Slice-Reducer wie diesen zu identifizieren
Weg, um die Boilerplate-Bedenken auszuräumen, wo sie als dienen könnten
primitive Bausteine ​​für unsere Reduzierstücke.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/reactjs/redux/issues/2295#issuecomment-287820595 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AACourLpL5--NJiRzrWmKFJ31cl5DXJrks5rnqzxgaJpZM4MhnVF
.

Ich stimme den meisten Kommentatoren zu, die sagten, dass es besser ist, gängige Redux-Muster zu erklären, als einen Boilerplate-Reduzierer zu entwickeln. Meine Teamkollegen und ich begannen vor 1,5 Jahren mit Redux zu arbeiten und waren meistens verwirrt über die einfachsten Dinge: dass Redux hauptsächlich Event-Sourcing ist, dass dieselbe Aktion von mehreren Reducern verarbeitet werden kann, dass eine Aktion die gesamte Geschäftseinheit enthalten kann, nicht nur ihre ID , dass Reducer nur Funktionen sind und Sie mit ihnen alles machen können, was Sie wollen - komponieren, generieren, splitten usw. Wir haben häufige Fehler gemacht - Aktionen als Remote-Befehle verwendet und uns gefragt, warum man nicht den klassischen Methodenaufruf verwendet; erstellte riesige Middlewares und vermied Redux-Saga, weil "Generatoren zu kompliziert sind" (obwohl Redux-Saga hervorragend ist!), erstellte lange Dateien mit riesigen Schaltern. Dies liegt natürlich an mittelmäßigen Programmierkenntnissen, aber auch am Mangel an strukturierten Informationen. Heute ist die Dokumentation viel besser, vielen Dank an die Betreuer!

Dies ist ein sehr wertvolles Thema zu Redux als Bibliothek.

Dies ist grundlegendes Javascript-Refactoring. Wie ich schon sagte... "javascript" hat ein
viel "Boilerplate", bis Sie Dinge wie Abstraktion auf Ihren Code anwenden.
Redux ist nur Javascript. Daran ist nichts Magisches.

Perfekt, @blocka! Ich denke, diese Botschaft muss verbreitet werden.

Redux fühlt sich aufgrund seines minimalen Ansatzes für die Leute ungewöhnlich und unkonventionell an. Minimal fühlt sich für ein "Framework" im Allgemeinen seltsam an (minimaler Code, minimale Prinzipien).

Manche Leute sind es gewohnt, "framework-y"-Code zu schreiben, anstatt JavaScript selbst zu schreiben. Wenn Entwickler ein Framework verwenden, werden implizit integrierte Vorgehensweisen erwartet. Traurig wie die Hölle, aber wahr.

Ich glaube, dass der Einstieg mit Redux einfacher wird als je zuvor, aber wir müssen den Leuten immer noch klar machen, dass sie nicht erwarten, dass Redux alles macht. @gaearon sagt das die ganze Zeit klar, aber leider sind die Leute daran

Ich habe gestern einen kurzen Artikel darüber geschrieben: Mach nicht React oder Redux die Schuld . Natürlich kann ich in all dem falsch liegen.

Es gibt einen Präzedenzfall für Abstraktionsschichten über einer erweiterten Bibliothek. Erst kürzlich hat Tensorflow Keras als Abstraktion über die Kern-API hinzugefügt: http://www.fast.ai/2017/01/03/keras/.

Die Verwendung von TensorFlow gibt mir das Gefühl, nicht schlau genug zu sein, um TensorFlow zu verwenden. während die Verwendung von Keras mir das Gefühl gibt, dass neuronale Netze einfacher sind, als ich dachte. Dies liegt daran, dass die API von TensorFlow ausführlich und verwirrend ist und weil Keras die durchdachteste und ausdrucksstärkste API hat, die ich je erlebt habe. Es war mir zu peinlich, TensorFlow nach meinen ersten frustrierenden Interaktionen öffentlich zu kritisieren. Es fühlte sich so klobig und unnatürlich an, aber das war sicherlich mein Versagen.

Ich habe das Gefühl, dass dies für die meisten Neulinge, die zu Redux kommen, eine ähnliche Erfahrung ist. Ersetzen Sie Tensorflow durch Redux und Keras durch Jumpstate . Redux ist sehr mächtig, aber die Mehrheit der Benutzer benötigt wahrscheinlich nicht alle verfügbaren Kontrollmöglichkeiten. Höchstwahrscheinlich kommen sie von Angular oder lernen React + Redux in einem Bootcamp oder beim Anschauen verschiedener Tutorials. Während Redux für neue Benutzer nicht verdummt werden muss, ist es auch kein Anti-Muster, um eine einfachere Abstraktion bereitzustellen, die wahrscheinlich 80% der potenziellen Anwendungsfälle abdecken kann.

Wenn Redux so wäre, wie es ist, würden wir dieses Gespräch nicht führen. Unabhängig davon, ob Redux nützlich oder strukturell solide ist, fühlen sich die Leute immer noch "schlecht", wenn sie es zum ersten Mal lernen. Diese Gefühle sind gültig.

Die Leute, die in diesem Thread kommentieren, sind alle Redux-Experten -- natürlich sind wir mit Redux zufrieden; Wir haben seine Philosophie verinnerlicht und fühlen uns wohl, unsere eigenen Abstraktionen für die Verwaltung von "Boilerplate" zu machen. Wir sind nicht die Zielgruppe, für die dieser Thread gedacht ist. Wir brauchen etwas Empathie für Benutzer, die zum ersten Mal zu Redux kommen, vielleicht sogar zum ersten Mal zur funktionalen Programmierung.

Zum Beispiel: Hier ist eine Beschwerde, die ich häufig über Redux höre (die meiner Meinung nach nicht im Upthread erwähnt wurde): Es reicht nicht aus, nur Redux zu verwenden, Sie "müssen" auch React-Redux, Redux-Thunk, Redux-Actions usw .

Müssen Sie buchstäblich all diese anderen Pakete verwenden, um Redux zu verwenden? Nein.
Werden die meisten Redux-Benutzer einige oder alle dieser zusätzlichen Pakete verwenden? Jawohl.

Spielt die Anzahl der Pakete in package.json Rolle? Nein nicht wirklich.
Beeinflusst die Anzahl der Pakete in package.json das Gefühl der Leute? Absolut.

Nun, ich denke, es ist fair zu glauben, dass Redux selbst so bleiben sollte, wie es ist, und ein anderes Paket ( create-redux-app oder was auch immer) sollte sie zusammenbauen. Aber wir haben ein echtes Komplexitätsproblem in der Hand und es reicht nicht aus, den Benutzern RTFM mitzuteilen.

Unabhängig davon, ob Redux nützlich oder strukturell solide ist, fühlen sich die Leute immer noch "schlecht", wenn sie es zum ersten Mal lernen. Diese Gefühle sind gültig

Absolut. Aber nicht alle Menschen empfinden so. Einige tun. Denken Sie daran, dass Sie nie von Leuten hören werden, die keine Probleme hatten. Sie sehen nur diejenigen, die Ihnen Fragen stellen oder auf Stackoverflow/Reactiflux treffen. Von denen, die es nie tun, brauchen einige auch Hilfe, wissen aber nicht, wie sie darum bitten sollen ... und einigen geht es auch gut, und Sie möchten es ihnen nicht noch verschlimmern ... sei derjenige, der stattdessen in Foren kommt, und es wird ein Nettogewinn von null sein.

Redux wurde nicht ohne Grund populär. Viele fanden es verdammt gut und empfahlen es anderen :)

Nun, ich denke, es ist fair zu glauben, dass Redux selbst so bleiben sollte, wie es ist, und ein anderes Paket (create-redux-app oder was auch immer) sollte sie zusammenfügen.

Diese Idee hat mir gefallen. Man könnte argumentieren, dass bestehende Boilerplates es bereits lösen, aber React hatte zu der Zeit auch viele Boilerplates, in denen sich die Leute darüber beschwerten, dass sie mit Tools überfordert waren, wenn sie versuchten, in React einzusteigen. create-react-app war eine großartige Antwort auf all dies, da es für Anfänger viele Schritte eliminiert hat, um bereits in React _selbst_ einzusteigen.

Aber es ist immer noch Boilerplate unter der Haube. Wir müssen die Leute also immer noch dazu ermutigen, sich in das Ökosystem einzukaufen und klarzustellen, dass Redux selbst nicht viel vom Design her macht . Es ist nicht möglich, vor dem Ökosystem davonzulaufen, wenn Sie React oder Redux verwenden möchten.

Ich glaube jedoch nicht, dass das Einbinden von Paketen wie redux-thunk in Redux Core hier der richtige Weg ist.

Nur aus Gründen der Klarheit geht es bei den Ideen, die ich veröffentliche, nicht darum, Dinge direkt in den Kern aufzunehmen. Es geht darum, hypothetisch eine Art "vorgefertigte Konfiguration" oder "einfache Abstraktionsschicht" zu erstellen, die ein separates Paket oder CLI-Tool oder etwas wäre, eher in der Art von create-react-app .

Ich denke, ich sollte mich besser als Autor von Jumpstate/Jumpsuit einmischen.

TL; DR:
Redux ist schwer zu erlernen und schwer zu konfigurieren / zu integrieren, weil es so niedrig ist. Die Community könnte von einer standardisierten Redux-API auf höherer Ebene profitieren, die auf den 90%-Anwendungsfall ausgerichtet ist, um die Lernkurve zu erleichtern und sogar als Lösung für einfachere Projekte zu fungieren. Jumpstate versucht, dieses Problem zu lösen, ist aber keine langfristige Lösung. Wir müssen anfangen, mögliche Ideen (realer oder Metacode) vorzuschlagen, wie diese API aussehen könnte.


Redux ist sehr schwer von Anfang an zu erlernen und sehr oft genauso schwer in neue Konzepte wie Async-Logik, Nebeneffekte, benutzerdefinierte Middleware usw. zu integrieren. Ich selbst habe dies erst vor etwas mehr als einem Jahr erlebt, als ich war sehr neu für das Reaktions-Ökosystem.

Nur ein paar Tage in der Lernreaktion wurde mir sofort empfohlen, Redux zu lernen. Diese Empfehlung kam sowohl von sehr erfahrenen als auch von unerfahrenen Entwicklern, die dasselbe getan hatten (oder taten). Es wurde als die De-facto-Lösung für alles gefeiert, was über setState hinausging (lassen wir das setState-Gate jedoch davon fern 😉 ). All dies aus gutem Grund, denn Redux ist erstaunlich.

Ich kam unweigerlich auf die Lernkurve und als ich Hilfe suchte, stellte ich sofort fest, dass das Marketing und der dokumentierte Ansatz für Redux einen Ton annahmen wie "Redux ist hart, die Konzepte sind auf niedrigem Niveau, die API ist gesperrt und Sie müssen sich nur durchsetzen es."

Also habe ich das zusammen mit all meinen Kollegen gemacht. Wir haben es durchgezogen, weil wir dazu erzogen wurden. Auf dieser Reise wagte ich jedoch schon sehr früh, eine Abstraktionsschicht zu schaffen, die einige der Komplexität und erweiterten Funktionen, die Redux zu bieten hatte, vorübergehend und bewusst verbergen würde.

Ich brauchte keine benutzerdefinierten Aktionsersteller, wollte mich nicht um die Zuordnung von Aktionen und Dispatchern zu Komponenten kümmern und entschied mich wie viele andere für ein weniger ausführliches Reducer-Layout anstelle einer switch-Anweisung.

Es hat fantastisch funktioniert. So gut, dass es den Prozess des Erlernens von Redux für den Rest meiner Kollegen und anderen Entwickler beschleunigte, die ähnlich mit der Lernkurve zu kämpfen hatten.

Wir haben es so konzipiert, dass fortschrittliches oder "idiomatisches" Redux immer noch verwendet werden konnte, wenn wir es brauchten, aber wirklich für unseren 90%igen Anwendungsfall konzipiert.

Ich sage keineswegs, dass jumpstate alle Grundlagen abdeckt, tatsächlich müssen noch so viele Dinge geändert werden, damit sich jumpstate "idiomatisch" verhält (anpassbare Aktionsersteller, Entfernen globaler Aktionsimporte ... es gibt eine Menge) , aber es hat definitiv vielen Leuten geholfen, die Grundlagen zu erlernen und ihnen einen Weg gegeben, zu verstehen, wie Redux auf einer sehr einfachen Ebene funktioniert. Ich erhalte ständig die Nachricht in der Jumpstate-Slack-Organisation, dass jumpstate jemandem geholfen hat, Redux zu lernen.

Ob diese Leute heute noch Jumpstate verwenden oder nicht, spielt keine so große Rolle (aber viele Leute verwenden es heute noch in der Produktion). Was zählte, war die Erfahrung, die sie hatten und wie schnell sie im Redux-Ökosystem produktiv werden konnten.

Einige weitere Ideen, die mir für diese Diskussion in den Sinn kommen:

  • Schlagen Sie Meta-Beispiele vor, wie ein vereinfachtes Redux aussehen könnte, probieren Sie es einfach aus!
  • diskutieren Anforderungen für und beschließen einen Standard für die oft duplizierten und extrem meinungsstarken Redux-Middlekriege. Wir könnten mit der asynchronen Behandlung beginnen. Dies könnte so viel Fragmentierung in der Redux-Community lösen und dazu beitragen, dass jedermanns Bemühungen einen Unterschied zum langfristigen Überleben und zur Nutzung von Redux machen.

Wie viel davon könnte in irgendeiner Weise mit verbesserten Dokumenten gelöst werden?

Viel. Wenn es um die Redux-Dokumentation geht, habe ich das Gefühl, dass sie in vielerlei Hinsicht schlimmer ist als die Dokumentation von AngularJS 1, weil sie wie die von AngularJS unnötig ausführlich ist, aber im Gegensatz zu AngularJS verfehlt sie das Prinzip "zeigen, nicht erzählen".

Die Dokumentation von Redux bevorzugt Code-Snippets anstelle einer tatsächlichen Demonstration des Codes, was bedeutet, dass es zu viele "Hier ist eine Reihe von Code; wir werden Ihnen nicht sagen, wie es sich verbindet, aber vertrauen Sie uns, dass es funktioniert"-Momente. Die fehlende Möglichkeit, Beispiele in einem Browser auszuführen, bedeutet, dass der Benutzer gezwungen ist, seinem eigenen Instinkt zu vertrauen, dass das, was er lokal tut, funktioniert, und wenn etwas nicht funktioniert, ist er alleine unterwegs. Selbst die einfache Todo List App ist meiner Meinung nach kaum das beste "Hallo Welt"-Beispiel für Redux - sie könnte viel einfacher gemacht werden.

Diagramme würden hier sicherlich helfen. Zum Beispiel mag ich @sunjay ; Eine noch bessere Möglichkeit besteht darin, eine für das Todo-Listen-Beispiel selbst zu entwerfen – wie sind die Dateien verbunden usw. aus einer übergeordneten Sicht. Bilder eignen sich fast immer besser für die Übertragung von langem Text und können dazu beitragen, die Ausführlichkeit der Dokumente zu reduzieren. Die Bilder würden auch Anfängern helfen, den Fokus zu behalten und Redux als Ganzes besser zu verstehen.

Meine zwei Cent: Bitte Kern nicht ändern. Seine Brillanz liegt in seiner Einfachheit. An diesem Punkt würde das Hinzufügen von etwas wahrscheinlich das Ganze beeinträchtigen.

Die Benutzerfreundlichkeit und weitere Abstraktion kann im Userland erfolgen. Ich habe auch nicht das Gefühl, dass es eine offizielle oder idiomatische Möglichkeit geben muss, es zu verwenden. Es ist ein vorhersehbarer Zustandscontainer, das war's!

Es kann alleine stehen, lass es uns sein ❤️

Das heißt, natürlich, packen Sie es so, wie Sie möchten, indem Sie weitere eigene Bibliotheken darüber erstellen. Das mache ich auch, aber lasst uns den Kern nicht ändern, bitte schön.

@HenrikJoreteg , keine Angst! Ich bin mir fast sicher, dass nichts, was wir hier besprechen, jemals den Kern ändern wird. Der Kern ist vollständig und steht für sich allein. :)

Viel. Wenn es um die Redux-Dokumentation geht, habe ich das Gefühl, dass sie in vielerlei Hinsicht schlimmer ist als die Dokumentation von AngularJS 1, weil sie wie die von AngularJS unnötig ausführlich ist, aber im Gegensatz zu AngularJS verfehlt sie das Prinzip "zeigen, nicht erzählen".

Das ist sehr wahr. Eine Sache, als Redux neu war, war, dass die Dokumentation spärlich war, aber die Grundlagen waren vorhanden. Viele haben es angenommen, weil es "so einfach" war. Aber Online-Ressourcen versuchen jetzt, "reale World-Techniken" zu zeigen, die oft nur "meine Lieblings-Middleware" und "mein bevorzugtes Werkzeug zur Boilerplate-Reduktion" sind. Die Leute werden überfordert.

Es gibt etwas zu sagen über "weniger ist mehr"

@Phoenixmatrix , @Sylphony : Wie würde also eine mögliche

Persönlich, um es mit meinen obigen Vorschlägen für einen "Starter-Shop" zu kombinieren, würde ich es in zwei Teile aufteilen (nicht 2 verschiedene Sites / Dokumente, sondern 2 verschiedene Abschnitte).

Die "Redux-Architektur", die viele niedliche, einfache Zeichnungen enthalten würde, erklärt Aktionen und Reduzierungen, führt React-Redux und vielleicht Thunks ein, verwendet den "Starter Store", um jede Art von Vorabkonfiguration einzuschränken und zeigt, wie einfach es geht sein, eine einfache App zu erstellen, die ein paar Ajax-Anfragen ausführt und Dinge auf dem Bildschirm rendert.

Alles andere kann in einem Abschnitt "Erkunden" mit den fortgeschritteneren Konzepten behandelt werden. Selbst dann würde ich wahrscheinlich eine Menge Zeug rausreißen. Jemand hat mich heute darauf hingewiesen, dass es einen Abschnitt über mehrere Stores in einer App gibt. Das ist gut zu wissen, aber die Verwendungsmöglichkeiten dafür sind wirklich fortgeschritten. Ich glaube nicht, dass ein Neuling darüber stolpern muss, ohne hinzuschauen.

Bessere Dokumente sind immer eine gute Idee, aber ich denke nicht, dass das das Kernproblem hier löst. Abstraktionsbibliotheken werden aufgrund der Boilerplate und der Ausführlichkeit der Redux-API geschrieben und übernommen. Dieselben Bibliotheken fragmentieren die Redux-Community, weil sie offensichtlich auf der einen oder anderen Ebene benötigt werden. Es ist frustrierend, wenn dieselben Autoren, die aktiv versuchen, zum Ökosystem beizutragen, öffentlich abgewiesen und entlassen werden, weil sie "Redux nicht verstehen". Wenn die Community stattdessen eine einfachere Abstraktion erstellen kann, die nicht Teil des React-Kerns ist, aber bis zu einem gewissen Grad "gesegnet" ist, gewinnen alle. Hardcore-Benutzer verwenden Redux weiterhin unverändert, andere können eine Abstraktion mit einer einfacheren/weniger ausführlichen API verwenden.

@derekperkins Wie kommen wir zu einem Konsens über eine "gesegnete" Bibliothek? Wie entscheiden wir, was drin ist und wer daran arbeitet?

Ich bin für so etwas, aber wie vermeiden wir es, einfach eine weitere Bibliothek zu erstellen, die nur einige Leute verwenden, und damit das Ökosystem noch weiter zu fragmentieren.

Relevante xkcd: https://xkcd.com/927/

Ja, Reduxs Kern und Reagieren-Redux kommen einem Konsens so ziemlich nahe, wie man nur bekommen kann. Sogar Redux-Thunk und Redux-Aktionen sind ziemlich grenzwertig, denn selbst auf dieser Ebene hat die Mehrheit der Leute unterschiedliche Bedürfnisse.

Das Reduzieren von Boilerplate in Redux ist eine Frage von "Ich brauche nicht"Also abstrahiere ich es weg. Aber selbst für Neulinge variiert "dieser Teil" dramatisch.

Verdammt, wir haben viele (mehrere Dutzende) Redux-Apps am Werk und es ist schwierig, einen gemeinsamen Boilerplate-Reduktions-Stack zu erstellen, da unterschiedliche Apps unterschiedliche Anforderungen haben. Es ist ganz einfach, wenn Sie eine einzelne App haben oder einige mit den gleichen Anforderungen. Auch kleine unterscheiden sich ziemlich.

Die Idee hier ist nicht, ein Toolkit zusammenzustellen, das alle Probleme für alle Menschen löst. Am Beispiel von CRA: Es gibt unzählige Möglichkeiten, Babel und Webpack und ESLint zu konfigurieren. CRA bietet eine einzige, eigenwillige Möglichkeit, sie alle ohne Probleme für den Benutzer zum Laufen zu bringen, und wählt bewusst eine Reihe von Einstellungen aus, die die Dinge für die Lernenden verbessern. Anschließend kann der Benutzer die Kontrolle über die Konfiguration übernehmen, _wenn er möchte_.

Es wird auch nicht versucht, jeden einzelnen Anwendungsfall zu lösen. CRA versucht nicht, fortgeschrittenes Code-Splitting, mehrere Einstiegspunkte, SSR oder ähnliches anzugehen. Die CRA-Dokumente _do_ weisen auf andere Tools und Optionen hin, die möglicherweise mehr Konfigurierbarkeit bieten und für bestimmte Anwendungsfälle besser funktionieren.

Das ist eine großartige Möglichkeit, es auszudrücken. Etwas, um schnell aufzustehen und zu laufen, dass
beinhaltet nur die Installation von Redux und dieser hypothetischen Konfigurationsschicht? Dass
das wäre großartig.

Eine andere Idee, die ich hatte, wäre ein Flag, das Sie im Dev-Modus setzen könnten, das könnte
Achten Sie auf inkrementelle Lernmöglichkeiten für den Benutzer und zeigen Sie diese auf. In
Auf diese Weise könnte die Abstraktionsschicht als interaktives Lehrwerkzeug dienen.
Am Montag, 20. März 2017 um 16:14 Uhr Mark Erikson [email protected]
schrieb:

Die Idee hier ist nicht, ein Toolkit zusammenzustellen, das alle Probleme löst
Für alle Leute. Am Beispiel von CRA: Es gibt unzählige Möglichkeiten zur Konfiguration
Babel und Webpack und ESLint. Was CRA tut, ist ein einzelnes, meinungsstarkes
Möglichkeit, sie alle ohne Probleme für den Benutzer zum Laufen zu bringen, und es
wählt bewusst eine Reihe von Einstellungen aus, die es besser machen für
Lernende. Es ermöglicht dem Benutzer dann, die Kontrolle über die Konfiguration zu übernehmen, wennsie wollen .

Es wird auch nicht versucht, jeden einzelnen Anwendungsfall zu lösen. CRA versucht es nicht
Bewältigen Sie erweiterte Code-Aufteilung, mehrere Einstiegspunkte, SSR oder ähnliches
das. Die CRA docs tun Punkt zu anderen Tools und Optionen , die bieten kann
mehr Konfigurierbarkeit und funktionieren für bestimmte Anwendungsfälle besser.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/reactjs/redux/issues/2295#issuecomment-287914805 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AFUmCactFzsw7etmGGP8MFK6kfNaOzTJks5rnvorgaJpZM4MhnVF
.

@sunjay Ich wusste, was das für ein xkcd-Link war, ohne dass ich klicken musste. :)

Ich stimme @markerikson zu. Dies ist nicht der Versuch, jeden Grenzfall für jede Person zu behandeln. Es ist eine rechthaberische Aussage von Redux-Kernentwicklern, die sagt: "Dies ist ein guter Weg, um die Dinge zum Laufen zu bringen". Es gibt vernünftige Standardeinstellungen, die bei Bedarf überschrieben werden können, aber ich würde wetten, dass die Standardeinstellungen für 80% der Entwickler funktionieren.

Das kann auf Core Redux geschrieben sein oder nicht. Ich denke immer noch, dass es einen Platz für etwas wie Jumpstate gibt, das mehr als nur die Lernkurve beschleunigt.

Die Redux-Lernkurve kann steil sein, aber sobald Sie Konzepte verstanden haben, entfällt oft der Bedarf an Abstraktionsschichten

Ich denke, das stimmt bis zu einem gewissen Grad, bedeutet aber nicht unbedingt, dass Sie die Abstraktionsschicht immer eliminieren möchten. Obwohl ich in der Vergangenheit C geschrieben habe und die Speicherzuordnung verstehe, schreibe ich viel lieber in Go, wo die Garbage Collection für mich erledigt wird. Gemäß meinem Tensorflow-Beispiel zuvor wäre es performanter, in die APIs der unteren Ebene zu schreiben, aber es gibt auch viel über die Benutzerfreundlichkeit der Python-Keras-Abstraktion zu sagen. Ebenso ist es für Redux vs. Jumpstate (oder welche Abstraktion auch immer von diesem Problem herrührt) nicht so, dass Boilerplate nicht unbedingt schwer zu schreiben ist, es ist nur umständlich für die meisten Anwendungsfälle, die nicht die Flexibilität von rohem Redux benötigen.

Wenn es nach mir ginge, würde ich das gerne sehen:

  • Ein Flow/TypeScript-freundliches Subset, das einfacher zu tippen ist als Vanilla Redux.
  • Konstanten nicht so sehr betonen (machen Sie einfach die Verwendung von String-Literalen sicherer).
  • Die Unabhängigkeit von React oder anderen Ansichtsbibliotheken beibehalten, aber die Verwendung vorhandener Bindungen vereinfachen (zB Bereitstellung von mapStateToProps Implementierungen).
  • Beibehaltung der Redux-Prinzipien (serialisierbare Aktionen, Zeitreisen und Hot Reloading sollten funktionieren, Aktionsprotokoll sollte sinnvoll sein).
  • Unterstützung von Code-Splitting auf eine einfachere Weise out of the box.
  • Ermutigen Sie die Anordnung von Reduzierern mit Selektoren, und machen Sie das Zusammenschreiben weniger umständlich (denken Sie an Reduzierer-Selektor-Bundles, die einfach zu schreiben und zusammenzustellen sind).
  • Anstatt Aktionsersteller mit Reduzierern zusammenzufassen, sollten Sie die Aktionsersteller vollständig loswerden und eine Viele-zu-Viele-Zuordnung von Aktionen zu Reduzierern natürlich machen (anstatt wie die meisten Bibliotheken davor zurückschrecken).
  • Machen Sie vernünftige Leistungsstandards, damit die Speicherung über Reselect für allgemeine Anwendungsfälle „einfach funktioniert“, ohne dass Benutzer diesen Code schreiben.
  • Enthält integrierte Helfer für Indizierung, Normalisierung, Sammlungen und optimistische Aktualisierungen.
  • Mit integrierter testbarer asynchroner Flow-Unterstützung.

Natürlich zusätzlich zum Kern, obwohl es in Ordnung ist, es als offizielle Redux-Sache zu brandmarken.
Außerdem werde ich das nicht schreiben. Doch kannst du.

Für mich vor ein paar Monaten, als ich redux lerne, habe ich das Dokument gelesen, verstehe es aber nicht sehr gut, also verbringe ich 2 Tage damit, den src-Code zu lesen, dann jede Beschreibung über api von der doc wird klar .

Und dann wird der Gedanke über das "State Design", "Reducer Division", "Middleware Design", "Async Solution"...... Kapitel klar, wenn ich das Projekt in den nächsten Monaten entwickle.

Ich denke, das Lesen des src-Codes ist der beste Schritt , um redux zu lernen, und erst danach können Sie die Umgebung von redux reibungsloser verstehen und erkunden.

Async-Unterstützung standardmäßig.

Ich meine, keine Notwendigkeit, ein anderes Plugin wie redux-thunk, redux-saga .

Async-Unterstützung standardmäßig

Das tut es, es ist nur so, dass die Leute es 0,5 Sekunden lang ansehen, bevor sie nach etwas Besserem suchen. Nichts hindert Sie daran, APIs in Ihren Komponenten aufzurufen und dann Dispatch in den Rückruf-/Versprechensauflösungen aufzurufen. Es ist nur so, dass die Leute es sofort externalisieren wollen (ich eingeschlossen). Aber Sie können Asynchronisierung ohne Middleware problemlos durchführen.

Der Kommentar von

Das finde ich tatsächlich faszinierend.

Meine eigene Redux Abstraktion Bibliothek macht fast ganz das Gegenteil. Ich finde einen immensen Wert in Single-Reducer-Aktionen, in der Bündelung atomarer Reducer-Funktionen mit ihren Aktionscodes und Selektoren, in der Beseitigung von Strings zugunsten von Objektschlüsseln. Es ist meine eigene 90%-Lösung, die CRA in der Einstellung ähnlicher ist als alles andere.

Der interessante Punkt ist sehr viel: Welche Probleme versuchen wir zu lösen? Es gibt viele Probleme mit mehreren verfügbaren Lösungsräumen. Wenn Dan Redux 2.0 so bauen würde, wie er es beschrieben hat, würde ich auch meine eigene Abstraktionsbibliothek neu aufbauen!

@jbellsey Redux ist großartig darin, der App weltweit Aktionen und Zustände bereitzustellen – aber in einem definierten Umfang – Sie können unendlich viele Instanzen von Redux Store haben, aber Sie können sie kombinieren. Grundsätzlich ist dies für Bibliotheken nützlich. Wenn Sie eine Bibliothek sprechen über redux innen zu sehen, können Sie profitieren ...

Welche Probleme versuchen wir zu lösen?

Globaler Status der App. R a eliable E sthetics D elivered U nified e X tensible: heart:

Niemand will Globals. Aber jeder braucht einen :tm:

Bitte halten Sie Redux so einfach, wie es jetzt ist. Es ist Muster. Kochbücher entstehen immer um :100:

@markerikson Wäre es eine gute Idee, ein Dokument / eine Tabelle zu erstellen, um diese Gedanken zu organisieren? Es gab schon einige tolle Ideen und es sind erst 48 Stunden vergangen 🎉

Für mich würde ich den Leuten nicht empfehlen, Thunks oder Sagen zu verwenden. Lernen Sie stattdessen Dependency Injection-Techniken in JavaScript.

Redux wird einfacher, wenn ich es als einfache Datenbank behandle:

  • Ich teile Redux den Anfangszustand mit und wie sich eine Aktion (ein Ereignis) auf den Zustand der Anwendung auswirkt. (Wie Datenbankschema und gespeicherte Prozeduren.)
  • Dann kümmert sich Redux um die Verwaltung und Benachrichtigung der Listener und bietet Möglichkeiten, den Zustand zu überprüfen und zu debuggen.

Für mich ist das alles, was Redux für mich ist (ich würde nicht erwarten, dass eine Datenbank einen HTTP-Aufruf macht). Für I/O und asynchrone Sachen führe ich es außerhalb von Redux aus. Dadurch bleibt mein Redux-Store vorhersehbar. Die Typsignatur ist immer store.dispatch(actionObject) . Keine Dispatching-Funktionen und keine versteckte Bedeutung innerhalb der Aktion (zB das Dispatching einer Aktion führt nicht zu einem API-Aufruf).

@tannerlinsley : Ja,

Ein Nachteil für mich, wenn ich diese Diskussion beginne: Ich habe bereits eine Menge Zeug, an dem ich arbeiten und über das ich schreiben muss. Vieles davon ist selbst auferlegt, aber es bedeutet, dass ich nicht genug Zeit habe, um an einigen der Redux-bezogenen Themen zu arbeiten, die ich untersuchen möchte, geschweige denn Dinge wie eine große Überarbeitung von Dokumenten anzugehen oder ein neues Toolkit aufzubauen kratzen.

Ich möchte unbedingt an diesen möglichen Bemühungen beteiligt sein, aber es werden andere Leute brauchen, die mitmachen und zusammenarbeiten. (Berühmte letzte Worte jedes OSS-Betreuers... :))

Redux wird einfacher, wenn ich es wie eine einfache Datenbank behandle

Das empfehle ich!

  • Halten Sie Ihren Shop normalisiert
  • Sie können Daten vorbereiten – wie Ansichten. Tun Sie dies durch dedizierte Reduzierstücke — Sie brauchen dann nicht reselect . Erwägen.
  • Aktionen sollten keine anderen Aktionen auslösen – das kann einfach aussehen. Aber es ist schwierig, wenn Sie componentDidMount Hooks haben. Ich weiß nicht, wie ich das lösen soll. Das hier in der Hierarchie nach oben zu verschieben ist nicht immer einfach

FWIW, ich habe Redux mit D3.js (ohne React) verwendet und es läuft ziemlich gut. Einige Beispiele hierfür sind in d3-component aufgeführt .

Was ich an den React Redux Bindings am meisten vermisse ist connect . Der Punkt, der mich aus der obigen Gliederung / Vision von @gaearon am meisten interessieren würde, ist "Bereitstellung von mapStateToProps Implementierungen".

Sie können Daten vorbereiten – wie Ansichten. Tun Sie dies durch dedizierte Reduzierstücke – Sie müssen dann nicht erneut auswählen. Erwägen.

Ja, das ist ein bisschen was Twitter in seinem Speicher tut, zumindest glaube ich - sie haben entities Niederlassung , die Stammgäste IDs Datenkarten und dh enthält timeline Ansicht , die im Grunde Sie die wichtigsten Futtermittel ist Sehen Sie, welche ID-Referenzen auf den Entity-Zweig enthalten, aber bereits vorberechnet sind.

Und genau das strebe ich bei den kommenden Refactorings an, da die Neuauswahl hochdynamischer Listen... auf lange Sicht ziemlich umständlich sein, da Sie sich oft an 2 Orte (oder mehr) erinnern müssen.

@stefensuhat als ich versuchte, Redux selbst zu implementieren, habe ich eine Promise-Schleife verwendet, um asynchrone Aktionen zu ermöglichen. Sie können es sich ansehen unter

@gaearon stimme deiner Liste

Zu dieser guten Idee möchte ich auf jeden Fall beitragen!

@markerikson @tannerlinsley

Was die Organisation dieser Ideen angeht, schlage ich vor, dass Sie nach der Erstellung der Tabelle Github-Probleme in den entsprechenden Repos erstellen, um die Entwicklung zu verfolgen. Sie sollten dann hier mit einer Liste dieser Probleme einen Kommentar abgeben.

Dies garantiert nicht, dass etwas Bestimmtes mit Redux ausgeliefert wird, aber es gibt Leuten, die sich für diese bestimmte Sache interessieren, die Möglichkeit, die Diskussion zu verfolgen und zusammenzuarbeiten, um sie zu verwirklichen.

Die Last, diese Vorschläge in die Realität umzusetzen, liegt bei uns allen, die an jedem neuen Feature oder Ansatz interessiert sind. Obwohl Mark die Diskussion begonnen hat, bin ich mir sicher, dass niemand von ihm erwartet, dass er alles umsetzt. :)

Ja, die Liste von @gaearon ist ideal, aber wie einige Leute bereits erwähnt haben, ist das eine Menge Zeug. Jeder, der versucht, es direkt anzugehen, wird in Vergessenheit geraten. Ich würde es gerne sehen, wenn es trotzdem passiert, aber ich denke, kleinere Teile sollten gleichzeitig angegriffen werden, anstatt eine vollständige Schicht darüber aufzubauen (wiederum mein Beispiel eines vorkonfigurierten Starter-Stores zu pushen;) )

Wenn/wenn jemand versucht, diese ganze Liste anzugreifen, denken Sie auch daran, welche anderen Tools und Frameworks außerhalb von Redux und sogar außerhalb von React existieren. React/Redux hat eine Reihe interessanter Vorteile gegenüber Vanilla Flux, gegenüber MobX, gegenüber VueJS und seinem Ökosystem gegenüber Angular. Was auch immer die Community tut, sie möchte sich wahrscheinlich auf einige dieser Vorteile konzentrieren (von denen einige auf der Liste von @gaearon stehen ) und sicherstellen, dass die darauf aufbauende Schicht nicht völlig überflüssig wird. Viele Dinge wie Zeitreise-Debugging, Middleware-Ökosysteme usw. sind an anderer Stelle verfügbar.

Beispiel, das ich mir ausdenke: Es kann verlockend sein, ein Modul zu erstellen, mit dem Sie eine Funktion erstellen können, die einen automatisch generierten Reducer automatisch aktualisiert. Aber sobald Sie das getan haben, haben Sie MobX repliziert, so dass dies nicht sehr nützlich ist.

@Phoenixmatrix ja, was ich meine, ist, dass Redux eine Standard-Middleware hat, sodass wir keine externe verwenden müssen. 😄

Ich sehe nicht wirklich etwas Falsches an der aktuellen Implementierung von Redux. Boilerplate existiert, aber es ist wirklich keine große Sache, wenn Sie ein Typensystem haben.

Ein großes Problem für mich ist, dass die Leute anscheinend nicht verstehen, dass wir Frontend-Anwendungen entwickeln, die viel komplexer sind als noch vor einigen Jahren. Wenn wir größere, komplexere Anwendungen mit großen Teams erstellen, ist es für mich normal, dass der Schwierigkeitsgrad erheblich zunimmt, dass neue Muster entstehen, die Leute diese Schwierigkeit jedoch ablehnen.

Ich sage nicht, dass wir nicht versuchen sollten, die Dinge einfacher zu machen oder Boilerplate zu reduzieren, aber dass die Leute nicht anfangen sollten, Redux zu verwenden und sich über die damit verbundenen Boilerplates beschweren, ohne die Kompromisse zu verstehen und das Gesamtbild zu sehen.

Als Redux erstellt wurde, haben viele Leute (mich eingeschlossen) versucht, dieses Ding zu bauen, und @gaearon hat die beste Implementierung erhalten und sehr gute Arbeit an Tools / Demo geleistet. Es (und auch Flux) bekamen anfangs viel Traktion, nicht nur wegen der Zeitreise, sondern auch, weil das Konzept für viele Leute nicht neu war und sich sofort natürlich anfühlte.

Die Leute sehen Redux als neues glänzendes Spielzeug (das scheint in der Praxis nicht so einfach zu sein). Aber nichts an Redux ist wirklich neu, außer dass jemand diese Konzepte auf elegante Weise auf das Frontend portiert hat. Die Muster von Redux und seinem Ökosystem werden bereits in verteilten Systemen, ereignisbasierten Backend-Anwendungen, Domain-Driven-Design verwendet, und Personen mit Hintergrundwissen werden Redux sehr leicht verstehen.

Leider möchten die Leute Schritte überspringen und Redux verwenden, ohne etwas über die damit verbundenen allgemeineren Muster zu wissen. Persönlich würde ich jedem empfehlen, der etwas Ernsthaftes in Redux bauen möchte, ein minimales Hintergrundwissen in verteilten Systemen zu haben. Das mag seltsam erscheinen, aber ich denke, diese Art von Hintergrund kann Ihnen jetzt und in den kommenden Jahren einen sehr ernsthaften Vorteil verschaffen.

Was bauen wir genau, wenn wir eine Frontend-Anwendung erstellen?

  • Wir bauen ein Mitglied eines verteilten Systems
  • Dieses Mitglied enthält nur eine Teilmenge der Daten des allgemeineren Systems
  • Dieses Mitglied hat ziemlich begrenzte Kapazitäten (Speicher, Bandbreite, Netzwerkstabilität...)

Also versuchen wir, etwas sehr Komplexes zu bauen. Wir haben Einschränkungen, die schwieriger zu handhaben sind als Datenbankentwickler, aber wir möchten, dass es einfacher ist, ohne das Vorwissen von Leuten wiederzuverwenden, die sich viele Jahre intensiv mit diesen Problemen beschäftigt haben. Glaubst du nicht, dass man sich schon Gedanken gemacht hat, wie man den Staat innerhalb einer DB strukturieren kann? wie kann man es abfragen?

Ich sage nicht, dass wir heute nicht pragmatisch sein sollten, Anwendungen versenden und mit unserem aktuellen Wissen Fehler machen, sondern vielmehr verstehen und anerkennen, dass das, was wir bauen, nicht mehr einfach ist und zusätzliches Wissen erfordert. Redux könnte ein guter Weg sein, um dieses Wissen zu erlangen, und Sie können es zunächst pragmatisch einsetzen, aber unterschätzen Sie nicht, wie viel Frontend-Entwicklung Ihnen in den kommenden Jahren unangenehm sein wird.

Leider möchten die Leute Schritte überspringen und Redux verwenden, ohne etwas über die damit verbundenen allgemeineren Muster zu wissen.

Im Guten wie im Schlechten hat Redux den Kampf um das Zustandsmanagement von React im Wesentlichen gewonnen. Damit verbunden ist die Fähigkeit, das Ökosystem zu gestalten. Es wird immer Entwickler geben, die einfach nur etwas wollen, das funktioniert, und es gibt viele einfachere Anwendungen, bei denen das alles ist, was notwendig ist. Entweder werden die Leute weiterhin andere Abstraktionsschichten verwenden oder sie können über eine einfache Bibliothek an die richtigen allgemeinen Muster herangeführt werden.

Persönlich würde ich jedem empfehlen, der etwas Ernsthaftes in Redux bauen möchte, ein minimales Hintergrundwissen in verteilten Systemen zu haben. Das mag seltsam erscheinen, aber ich denke, diese Art von Hintergrund kann Ihnen jetzt und in den kommenden Jahren einen sehr ernsthaften Vorteil verschaffen.

Dies ist der Kern des Problems. Redux funktioniert wie es ist großartig für Leute, die es verstehen. Es ist jedoch nicht unbedingt schlecht, es zu vereinfachen. Die meisten Leute schreiben keinen Assemblercode mehr, obwohl das Verständnis normalerweise Ihnen hilft, besseren Code zu schreiben. Das ist einfach nicht, wo die meisten Leute anfangen.

Viele weitere gute Kommentare rundum. Hier gibt es jede Menge Ideen, die wir weiter erforschen könnten und sollten.

Mal sehen, ob wir anfangen können, einige potenziell umsetzbare Ideen zu entwickeln. Ich beginne mit einem kleinen Basiskonzept:

Erstellen Sie ein neues Paket namens, ich weiß nicht, redux-starter oder so. Dieses Paket kann von redux-actions , redux-thunk und redux-logger und möglicherweise einer auf Versprechen basierenden Middleware abhängen. Es würde eine Funktion mit der Signatur function createReduxStore({reducers, middleware}) {} bereitstellen (basierend auf @Phoenixmatrix oben ). Könnten Sie sich nicht einmal die Mühe machen, Middleware zu akzeptieren?

Die Funktion createReduxStore() würde sich um die Behandlung von applyMiddleware kümmern und das Hot-Reloading für den Root-Reducer einrichten sowie die Redux DevTools-Erweiterung konfigurieren. Wenn keine Middleware bereitgestellt wird, werden die enthaltenen standardmäßig konfiguriert. Dies könnte dem Einrichtungscode für configureStore in meiner Beispiel-App "Project Mini-Mek" ähneln .

Dies würde zumindest den für den Einstieg erforderlichen Einrichtungsaufwand minimieren und einen bescheidenen Satz nützlicher Funktionen bereitstellen.

Ja, das gefällt mir (naja, ich mag keine Redux-Aktionen und Middlewares auf Versprechensbasis für neuere Benutzer, aber ich lasse Sie mit dem Bikeshedding hier viel Spaß haben). Würde mich nicht die Mühe machen, Middleware zu akzeptieren, einfach createStarterStore (Reduzierer).

Vielleicht ersetzen Sie sogar den CombineReducer, damit Sie einfach tun können:

const store = createStarterStore({
   foo,
   bar,
   baz
});

wo foo bar baz Reduzierstücke sind.

Drat. Habe gerade festgestellt, dass "eine Bibliotheksfunktion, die HMR für den Root-Reducer einrichtet" wahrscheinlich nicht funktioniert, denn selbst wenn wir dem Benutzer erlauben würden, den Pfad zu seiner Root-Reducer-Datei zu übergeben, wird einer oder beide der module.hot.accept() API und require(path) Reimportschritt wollen Pfade, die zur Build-Zeit statisch analysierbar sind und keine Variablen. (Ich denke... ich könnte mich irren.) Oh, gut.

Aber ja, createStarterStore() könnte entweder den Root Reducer oder das Slices-Objekt akzeptieren.

Persönlich würde ich jedem empfehlen, der etwas Ernsthaftes in Redux bauen möchte, ein minimales Hintergrundwissen in verteilten Systemen zu haben. Das mag seltsam erscheinen, aber ich denke, diese Art von Hintergrund kann Ihnen jetzt und in den kommenden Jahren einen sehr ernsthaften Vorteil verschaffen.

@slorber Da stimme ich dir zu.

Leider möchten die Leute Schritte überspringen und Redux verwenden, ohne etwas über die damit verbundenen allgemeineren Muster zu wissen.

Aber nicht wirklich auf diesem. Einige Leute kennen die Muster von Redux, und genau aus diesem Grund haben sie sich dafür entschieden, es zu verwenden. Der Wunsch, etwas Einfaches (oder zumindest Einfacheres) zu verwenden, bedeutet nicht unbedingt, dass der Benutzer nicht in der Lage ist, eine schwierigere Implementierung zu verwenden. Es spart nur Zeit und Mühe.

An dem Ort, an dem ich arbeite, verwenden wir Redux jetzt seit einem Jahr und haben den gleichen Code kopiert/eingefügt (nur ein wenig modifiziert), um dem Store neue Ressourcen hinzuzufügen, weshalb wir irgendwann das Gefühl hatten die Notwendigkeit, eine Schicht über Redux zu implementieren, um diese redundante Boilerplate zu abstrahieren.
Meiner Meinung nach vereinfacht diese Idee nicht nur die Verwendung von Redux, sondern reduziert auch die Boilerplate für die gängigsten Teile (in gleicher Weise reduziert react-redux die Boilerplate, wenn Redux zusammen mit React verwendet wird).

Sehr interessante Diskussion. Meine zwei Cent als Redux User seit den Anfängen:

Anfangs wurde Redux, soweit ich mich erinnere, eher als Protokoll oder eine Reihe vernünftiger Konventionen denn als Framework zum Erstellen von Apps angesehen. Diese Strenge ist einer der Gründe, warum Redux für neue Leute überwältigend und mühsam zu skalieren sein kann, ohne eigene Abstraktionen zu rollen. Aber die einfache Art und Weise, wie es das Chaos der Verwaltung des Staates im Jahr 2015 durchbrochen hat, ist auch ein Grund, warum es so erfolgreich war, und der Minimalismus hat es erstaunlichen Frameworks wie Apollo ermöglicht, die Arbeit für verschiedene Projekte (insbesondere Entwicklungstools) zu huckepack zu tragen und einen vertrauten Weg zu geben bei Bedarf in der Zustandsverwaltung "auf eine niedrigere Ebene fallen" zu lassen.

Ich denke, es ist klar, dass als "Low-Level"-Bibliotheksredux ein großer Erfolg war, und als funktionsreiches Framework zum Erstellen von Apps ist es noch nicht ganz da. Eine Sache, auf die man achten sollte, ist, dass Redux bei der Weiterentwicklung seine Rolle als Industriestandard-"Protokoll" für Projekte wie Apollo nicht bricht.

Zu diesem Zweck kann das aktuelle Redux vielleicht zu einem Paket wie redux-core , und redux selbst erhöht die Abstraktionsebene, um eine empfohlene Methode zum Erstellen von Apps zu bieten. Natürlich kann es eine Reihe von höherstufigen Alternativen zu diesem redux (wie Apollo oder etwas, das Sagas verwendet?) mit Redux-Core ...

Zur Verdeutlichung und Betonung noch einmal etwas wiederholen:

Jede Arbeit aus diesem Thread wird keine größeren Änderungen an der bestehenden Redux-Bibliothek beinhalten :) Eine Überarbeitung der Dokumentation ist durchaus möglich, und es könnte einige kleine Verbesserungen geben, aber das vorhandene redux Paket würde so bleiben, wie es ist.

Alles wie das gerade beschriebene redux-starter Paket oder der von Dan skizzierte "Framework"-y-Ansatz wäre ein neues Paket, das von redux abhängt.

Ich stimme dafür, dass wir das Paket wie von

Sie können Delux als Starter verwenden (jk)

Als starker Nutzer von @tannerlinsleys Jumpstate (und jetzt einer der Betreuer) bin ich unglaublich aufgeregt darüber. Meine Gründe für Jumpstate verwenden sehr kurz und bündig in @gaearon ‚s Original - Beitrag skizziert. Das heißt, es ist keine vollständige Lösung (es war nie beabsichtigt). Ich habe erst heute Morgen über ein paar Dinge nachgedacht, die noch hinzugefügt werden könnten, und dann habe ich diesen Thread entdeckt und festgestellt, dass ihr bereits darüber nachdenkt.

Langatmige Art zu sagen: Klingt großartig, ich bin dabei, ich bin mir nicht sicher, wie viel ich beitragen kann (ich werde es versuchen), aber Sie haben sicherlich eine Cheerleaderin.

Ich habe Jumpstate jetzt schon mehrfach verwendet, um Redux zu unterrichten und kann mit Zuversicht sagen, dass es die Lernkurve erheblich verkürzt hat. Ich denke an Redux wie HTTP und Jumpstate wie fetch. Ich liebe Redux und habe einige (lächerlich) komplizierte Dinge damit geschrieben, aber ich weiß auch, dass 90% Fall mehr als genug sind, um die meisten Dinge zu lehren.

Wenn Sie darüber nachdenken, ist dies ein großartiger Ort. Eine der Hauptbeschwerden über Frontend-Entwicklung und Javascript im Allgemeinen ist "das Fehlen von Standardbibliotheken". Die Sache ist, dass dies eine sehr neue Sache (TM) ist, vollständige Anwendungen im Browser entwickeln zu können. Endlich wächst der Druck, Standardbibliotheken zu benötigen . Da sind wir jetzt.

Re: Lernkurve, Eigensinn und Abstraktion:

Ajax scheint ein Bereich zu sein, in dem neue Lernende stecken bleiben, egal ob sie lernen, Thunks, Sagen oder Epen zu verwenden. Ein Bereich, in dem sie keine großen Schwierigkeiten zu haben scheinen, ist das Erstellen von Aktionen – da es sich nur um einfache alte Javascript-Objekte handelt, und wir haben die zusätzliche Klarheit, die die Flux-Standardaktionsspezifikation bietet. Diese Denkweise führte mich zu der Frage: Warum nicht eine Flux Standard Ajax Action entwickeln ?

Z.B

function fetchPosts(page) {
  return {
    type: 'FETCH_POSTS_REQUEST',
    // Ajax request setup
    ajax: {
      url: `/api/posts`,
      method: 'GET',
      data: { page },

      // Optional ajax meta attributes
      meta: {
        // Amount of time to debounce the execution of the request
        debounce: 400,
        // Amount of times to retry the request on failure
        retry: 2,
        // Amount of time before timing out
        timeout: 10000,  
        // The action type that cancels the request
        cancelType: 'CANCEL_FETCH_POSTS',
        // Strategy when multiple FETCH_POSTS_REQUESTs are in flight
        resolve: 'LATEST'
      }
    }
  };  
}

Die Ajax-Aktion würde von Middleware verarbeitet (die auf die Taste ajax in der Aktion reagieren würde).

Ich habe versucht, über Gründe nachzudenken, warum dieser Ansatz eine schlechte Idee wäre, habe aber noch keine Deal-Breaker in Betracht gezogen.
Einige Vorteile nach meiner Einschätzung:

  • eine drastische Verringerung der Anzahl der asynchronen Aktionen, die in Ihrer durchschnittlichen Anwendung erforderlich sind (da die asynchronen Aktionen im Zusammenhang mit Ajax wegfallen würden)
  • leicht zu verstehen, da wir es nur mit einfachen alten Javascript-Objekten zu tun haben
  • es ist deklarativ, Implementierungsdetails sind nicht wichtig
  • verschiedene Implementierungen konnten ohne Brüche ein- und ausgewechselt werden
  • es ist idiomatisches Redux (Aktionsprotokoll macht immer noch Sinn, serialisierbar usw.)

Ich kann einige Leute hören, die sich auf das Argument der Trennung der Belange berufen, aber ich würde argumentieren, dass dies eine natürliche Erweiterung dessen ist, was unsere Ajax-Anforderungsaktionen bereits tun. Derzeit richten sie eine Aktion mit einem ziemlich klaren Kontext ein, 'FETCH_POSTS_REQUEST' , aber mit zu wenig Kontext, um die Implementierung der Ajax-Anforderung abzustrahieren. Es bleibt kaum eine andere Wahl, als die Ajax-Anfrage manuell an anderer Stelle auszuführen.

Eine andere Sache, die mir in den Sinn kommt, ist die asynchrone Aktionsverkettung, die ich in einigen Dokumenten gesehen habe. Wir hatten nicht die Notwendigkeit, Anfragen auf diese Weise zu verketten, daher bin ich mir nicht sicher, wie weit diese Verkettung verbreitet ist, aber mein Bauchgefühl ist, dass dies außerhalb des Rahmens von dem liegt, was ich hier vorschlage (und vielleicht tut es das auch) nicht unter den in dieser Diskussion erwähnten Anwendungsfall von 90 % fallen).

Zusammenfassend lässt sich sagen, dass es durchaus möglich ist, dass eine solche Abstraktion dazu beiträgt, die Lernkurve und die Menge an Code zu vereinfachen, die zum Schreiben allgemeiner Redux-Anwendungen erforderlich ist. Hat jemand irgendwelche Gedanken zu diesem Ansatz - irgendwelche Deal Breaker, die Sie sich vorstellen können? @markerikson @gaearon

Stand der Technik: redux-axios-middleware

In diesem Thread passiert viel.

Zur Diskussion um Redux-Komplexität. Persönlich stimme ich nicht mit Leuten überein, die sich darüber beschweren, dass Redux kompliziert und ausführlich ist. Es ist ein Kompromiss, den Sie eingehen, wenn Sie eine Low-Level-Bibliothek verwenden, die auf Flux- und Elm-Architekturen basiert. Auf der Redux-Homepage wird angegeben, dass Sie es möglicherweise nicht benötigen. Aber wir haben immer noch Leute, die sich darüber beschweren, dass es kompliziert ist.

Redux ist so wie es ist. Glücklicherweise ist sich das Kernteam bewusst, dass es vollständig ist und nicht bereit ist, es zu ändern. Die darauf aufbauenden Abstraktionen sind großartig und jede von ihnen hat ihren eigenen Anwendungsfall. Dies ist, was Sie von einer guten und gut gestalteten Low-Level-Bibliothek erwarten würden.

Ich sehe das Problem nicht in Redux selbst, sondern in dem Fehlen einer progressiven, sofort einsatzbereiten Methode, um es zu erlernen. Wie bereits erwähnt, hatte React selbst das gleiche Problem und create-react-app war die Lösung.

Vielleicht ist das nicht einmal das Problem, da es dafür großartige Ressourcen gibt (zB Dans Egghead- Serie ). Vielleicht sind Leute, die eine Bibliothek verwenden möchten, die komplexe Probleme ohne Lernkurve löst, das Problem.

Jedenfalls geht es in diesem Thread nicht darum.

@markerikson Ich bin persönlich redux-starter zu helfen.

_Ich hätte aber gerne einen cooleren Namen_ :stuck_out_tongue:

Die Boilerplate, die für die Erstellung vieler Aktionen erforderlich ist, ist so ziemlich der einzige Nachteil, den ich bei Redux sehe.

Es ist sehr niedrig, aber das finde ich großartig. Das ist ein Grund, warum ich beispielsweise das Redux-Stil-Paradigma MobX vorziehe, obwohl ich seine Nützlichkeit verstehe und MobX verwenden würde. Aber das mache ich erst gerne, wenn ich Redux verstehe. Da Redux (oder das Redux-Muster im Allgemeinen) die Daten nicht besonders "hinter die Kulissen" gehen. Wo auch immer Code verarbeitet wird, haben Sie ihn im Allgemeinen geschrieben, und wenn nicht, können Sie ihn verstehen (wenn Sie sich die Zeit genommen haben, es zu lernen, dazu später mehr).

Die Sache ist die, als ich Redux zum ersten Mal lernte, war es viel zu verstehen, aber es war auch einfach. Etwas kann sowohl schwierig als auch einfach sein. Aus diesem Grund dachte ich jedoch: "Wow, dieses Konzept ist so logisch! Es macht so viel Sinn, ich wette, ich könnte es selbst machen!" Also habe ich für mein erstes Projekt, anstatt das Redux-Paket zu verwenden, meinen eigenen kleinen Redux-Shop erstellt.

Das hat mir nicht nur geholfen, das Konzept von Redux zu verstehen, sondern auch mein Verständnis von Javascript selbst sehr verbessert! (Dies ist aus der Perspektive von jemandem, der vorher so gut wie nichts über funktionale Programmierkonzepte wusste, daher kann Ihre Laufleistung variieren.) Das Konzept von Redux ist in seiner Einfachheit wirklich ziemlich brillant, aber auch unglaublich mächtig.

Ich denke, da Redux so beliebt ist, kann es, äh, "Buzzwordy-ness" Neuankömmlinge davon ablenken, wie großartig es in Javascript funktioniert. Ihre Mentalität könnte also sein: "Okay, ich habe React, Redux usw. usw., jetzt werde ich ein großartiger Programmierer und mache eine großartige App!" Nicht, dass daran etwas falsch wäre. Aber sie konzentrieren sich vielleicht nur darauf, ein glänzendes neues Tool verwenden zu wollen, um den Entwicklungsprozess zu beschleunigen, ohne zu verstehen, was das Tool funktioniert.

Sobald das Konzept verstanden ist, wird es sehr einfach, Redux (oder ein Redux-ähnliches Muster) dazu zu bringen, alle möglichen Dinge zu tun. Ich mag es aus dem gleichen Grund, warum ich React gegenüber anderen (immer noch großartigen) Tools wie Angular mag. _Es ist nur Javascript._ So funktioniert Javascript!
Wenn die notwendige Boilerplate durch ein Paradigma reduziert werden kann, wäre das großartig, aber ich denke, es ist ein kleiner Preis für unbegrenzte dd powaaaaaa.

IMO ist all dies "die Ausführlichkeit ist ein Kompromiss" nur Masochismus; die Ausführlichkeit nicht in Betrieb ist nichts, es ist ein Opfer Sie Redux zu verwenden , überhaupt zu machen. Ich mache Redux oder Javascript nicht die Schuld, ich möchte nur darauf hinweisen, dass dies keine wesentliche Komplexität ist. Elm verwaltet alles, was Redux erreicht, in weniger Zeilen und einfacherem Code.

Also schreiben wir die Boilerplate mechanisch aus. Jumpstate und ähnliches machen das Leben einfacher, aber es gibt Grenzen, was Sie zur Laufzeit tun können, und mit Typoskript/Flow hilft jumpstate nicht viel. Aber Codegen ist hart, und niemand möchte seinem ohnehin schon überlasteten Build-System noch etwas hinzufügen.

Wenn ich so etwas wie Elm-Code haben könnte, der in idiomatisches Redux übersetzt wurde ... Sei immer noch mein schlagendes Herz.

Hier sind einige meiner Ideen, ich hoffe, ich wiederhole die vorherigen Kommentare nicht:

Aktionsersteller können als Aktionstypen verwendet werden

Aktionen.js

export function increase() {}

Reducer.js

import { increase } from './actions.js';
export default handleActions({
    [increase]: (state) => state + 1
}, 0);

Da Funktionen eindeutige Referenzen haben, können wir sie als Bezeichner für Aktionen behandeln. Nicht FSA-kompatibel, spart aber viel Code und verhindert Fehler.

Aktionen können asynchron versendet werden

async function a() {

}
async function b() {
}
store.dispatch(a());
store.dispatch(b()); // b() will be dispatched after a() resolves

Auf diese Weise können Aktionsersteller asynchrone Funktionen sein und dennoch nacheinander abfertigen. Wie ich sehe, werden die Leute in vielen Situationen keine Middleware-basierten Lösungen benötigen und es wird viel Boilerplate-Code eingespart.
Dieses Konzept wird von einer Versprechensfabrik in Delux . umgesetzt

redux === Boilerplate

https://github.com/Emilios1995/redux-create-module

Aber ich denke, diese Funktion kann Ihr Leben vollständig retten.

Es lohnt sich, in diesem Thread zwischen zwei verschiedenen Ideen zu unterscheiden:

  • ein "Full-Service"-Redux-basiertes Framework
  • zusätzliche Funktionen im Redux-Core

Ich stimme @markerikson zu, dass Redux Core kein

Redux hat eine ziemlich kleine API-Oberfläche: createStore , applyMiddleware , combineReducers , bindActionCreators und compose . Aber die meisten davon sind Komfortfunktionen. Nur createStore ist unbedingt erforderlich, damit Redux funktioniert. Warum gehören diese in den Kern?

  • applyMiddleware erstellt eine vereinfachte Schnittstelle zum Speichern von Enhancern. Aber noch wichtiger ist, dass applyMiddleware die Middleware _interface_ als Standardmethode zum Hinzufügen von Effekten zu Redux-Stores unterstützt. Das Middleware-Ökosystem ist möglich, weil applyMiddleware eine vergleichsweise einfache Benutzeroberfläche hat und es Benutzern ermöglicht, viele Middleware gleichzeitig auszuführen.

  • combineReducers bietet eine bequeme Form der Reduziererzusammensetzung. Es ist bei weitem nicht die einzige Möglichkeit, Reduzierstücke zu komponieren, aber es ist sicherlich eines der nützlicheren Muster. Aber seine Präsenz im Redux Core bedeutet, dass es nicht nur verbreitet, sondern _ubiquitär_ ist. Jede nicht triviale Redux-App, die mir begegnet ist, verwendet combineReducers , um den Root-Reducer zu erstellen. Die Kehrseite davon ist, dass, weil combineReducers die einzige Form der Reduzierer-Komposition ist, die mit Redux geliefert wird, viele Benutzer zu glauben scheinen, dass dies die einzige Form der Reduzierer-Komposition ist, die es gibt.

  • bindActionCreators reduziert einige der Boilerplates rund um das Dispatching von Aktionen. Aber perverserweise ist bindActionCreators indirekt auch für Reduxs Ruf für Boilerplate verantwortlich. Dies liegt daran, dass die bloße Existenz von bindActionCreators die Verwendung von Action-Erstellern fördert. Dies wird besonders deutlich, wenn man die Prävalenz von Aktionserstellern (die von bindActionCreators "befürwortet" werden) mit Selektoren (die dokumentiert sind, aber keine äquivalente Kernfunktion haben) vergleicht. Ich habe viele Codebasen gesehen, die react-redux wobei mapStateToProps immer "maßgeschneiderte" Selektoren sind, aber mapDispatchToProps immer eine Objektkarte von vorgefertigten Aktionserstellern ist.

Keines davon ist für die Funktionalität von Redux wesentlich, aber alle sind für seine Benutzerfreundlichkeit unerlässlich. Keine dieser Funktionen schränkt die inhärente Flexibilität von Redux ein, aber durch die Verdinglichung allgemeiner Muster in aufrufbare Funktionen machen sie Entscheidungen weniger abschreckend. Und jede dieser Hilfsfunktionen wirft weitere Fragen auf:

  • Wenn Middleware eine Vereinfachung von Shop-Enhancern ist, gibt es dann andere Vereinfachungen, die weithin nützlich sein könnten?
  • Welche anderen Formen der Reduziererzusammensetzung könnten implementiert werden, anstatt nur zu dokumentieren? Reduzierobjekte ? Abhängige Reduzierstücke ? Lineare Komposition ?
  • Würde die Integration von Reselect die Leute dazu bringen, Selektoren zu erstellen und zusammenzustellen, wo sie es vorher nicht

Auch wenn die Antworten auf all dies negativ ausfallen, denke ich, dass wir uns und der Gemeinschaft einen Bärendienst erweisen, indem wir uns weigern, ihre Prämissen überhaupt zu berücksichtigen.

@modernserf : Zunächst

Es ist sehr interessant, dass Sie diese wegen der damit verbundenen Geschichte (für die ich gerade viel Zeit damit verbracht habe, für meinen Beitrag Das Tao von Redux, Teil 1 - Implementierung und Absicht zu recherchieren) redux-thunk ursprünglich direkt in Redux eingebaut , und react-redux wurde erst später ebenfalls herausgetrennt .

Sie haben Recht, dass diese Dienstprogramme tatsächlich bestimmte Nutzungsmuster kodifizieren. Diese Dienstprogramme sind jedoch enthalten, weil sie die _beabsichtigten_ Nutzungsmuster kodifizieren: Zusammensetzung von Slice-Reduzierern, eine Middleware-Pipeline für asynchrones Verhalten und anderes zentralisiertes Verhalten und Ersteller von gebundenen Aktionen, um den Prozess der Verteilung von Aktionen von Komponenten zu vereinfachen (insbesondere das Weitergeben von Funktionen). zu untergeordneten Komponenten). Ähnlich, obwohl Reselect nicht im Kern enthalten ist, hat Dan seine Erstellung ausdrücklich gefördert .

Also ja, jeder hätte sie schreiben können, aber indem wir sie eingebaut haben, haben wir die Leute dazu gebracht, diese speziellen Tools auf spezifische Weise zu verwenden. Da bin ich mir auf jeden Fall einig.

Zu deinen letzten drei Fragen:

  • Ich _schätze_ man könnte sagen, dass Middleware "eine Vereinfachung von Shop-Enhancern" ist, obwohl ich denke, dass das ihnen nicht gerecht wird. Es ist vielmehr ein Shop-Enhancer für einen sehr speziellen Zweck. Was andere Arbeiten im Zusammenhang mit Store-Enhancern angeht: Dan hat gesagt, dass der größte Teil des Redux-Kerns, den er noch ändern möchte, sich darauf bezieht, wie Enhancer initialisiert werden. Es gibt tatsächlich zwei "konkurrierende" PRs, um die Implementierung von Store Enhancer zu ändern, die sehr lange offen geblieben sind: @acdlites Version in #1706 und @jimbolla 's Version in #2214. Interessant ist auch, dass Jim eine Liste aller bekannten Shop-Enhancer zusammengestellt hat , um zu analysieren, wie die Community sie tatsächlich nutzt. Ich weiß, dass Jims Vorschlag dazu gedacht war, Enhancer-Autoren zu helfen, häufig gesehene Verhaltensweisen zu vereinfachen. Das ist also eine Richtung, die weiter erforscht werden könnte.
  • Es gibt definitiv noch viele andere Muster für die Zusammensetzung und Struktur des Reduzierers. Ich bin mir nicht sicher, was wir in Bezug auf "abhängige" Reduzierer genau tun könnten, da dies viel mehr Nischenanwendungsfälle ist und ziemlich App-spezifisch zu sein scheint. In einem ähnlichen Zusammenhang hatte Dan lange Zeit alle PRs geschlossen, die vorschlugen, combineReducers eine Art drittes Argument hinzuzufügen (und es gab _viele_ davon), aber schließlich erlaubte es #1768, für a weiterzumachen während. Auch diese PR ist ins Stocken geraten.
  • Der häufigste Anwendungsfall für Selektoren scheint das direkte Extrahieren von Zustandsbits und die Übergabe als benannte Requisiten zu sein. Wir haben auch eine offene PR für React-Redux zum Hinzufügen einer Objektkürzel-Syntax für mapState und haben zahlreiche Anfragen dafür erhalten, obwohl Sie dasselbe mit Reselects createStructuredSelector tun können.

Wie ich in diesem "Tao of Redux"-Beitrag dokumentiert habe, bestand das erklärte Ziel darin, die Redux-Kern-API so minimal wie möglich zu halten und darüber hinaus ein Ökosystem zu fördern . Darüber hinaus machte Andrew einen Kommentar zu der Absicht, bestimmte Plugins zu "segnen" :

Wie gaearon einmal sagte, (ich kann mich nicht erinnern, wo... wahrscheinlich Slack) wollen wir wie die Koa-of-Flux-Bibliotheken sein. Schließlich, sobald die Community reifer ist, ist geplant, eine Sammlung von "gesegneten" Plugins und Erweiterungen zu pflegen, möglicherweise unter einer reduxjs-GitHub-Organisation.

Zuvor hatte ich eine Art Abstraktionsbibliothek für "einfaches Redux-Setup" oder so ähnlich vorgeschlagen. Wäre so etwas oder zumindest diese Liste "gesegneter" Add-Ons ausreichend, wie Sie denken? (Und das hast du im ersten Kommentar dieses Threads tatsächlich auch getan.) Falls nicht, weitere Vorschläge oder Ideen?

Schließlich, sobald die Community reifer ist, ist geplant, eine Sammlung von "gesegneten" Plugins und Erweiterungen zu pflegen, möglicherweise unter einer reduxjs-GitHub-Organisation.

Das würde ich auch machen, obwohl ich wahrscheinlich noch einen Schritt weiter gehen würde: Ich würde das Projekt in ein Monorepo umstrukturieren, wo das aktuelle redux Paket so etwas wie @redux/core , gesegnet Bibliotheken wie reselect und redux-action werden in das Repository und den Namensraum gebracht, und das redux Paket selbst exportiert einfach alle diese Pakete in einen einzigen Namensraum.

Diese _Art von_ erfüllt die Einschränkung, den Redux-Kern nicht zu modifizieren. Außerdem wäre die erweiterte Version eine strikte Obermenge des Kerns – und damit abwärtskompatibel. Die neuen Funktionen wären ein reines Opt-In und hätten keinen besonderen Zugriff auf den privaten Status. Was das "Aufblähen" angeht - jede dieser Bibliotheken ist anfangs klein und sie sind so geschrieben, dass es trivial wäre, sie durcheinander zu bringen.

Wir haben auch eine offene PR für React-Redux zum Hinzufügen einer Objektkürzel-Syntax für mapState und haben zahlreiche Anfragen dafür erhalten, obwohl Sie dasselbe mit Reselects createStructuredSelector tun können.

Ich denke, das sollte dir etwas sagen.

Die von mir vorgeschlagene Monorepo-Struktur ist im Grunde die von Lodash verwendete Struktur. Nun -- Lodash ist eine interessante Bibliothek, nach der man modellieren kann: Es ist eine enorme Sammlung von Funktionen, von denen viele einfach selbst zu implementieren sind. Fast jede Funktion in lodash könnte als "Rezept" flexibler sein -- groupBy ist schließlich wirklich ein _Muster_; Wer sind wir, um zu sagen, für welche Datenstrukturen Sie es verwenden?

Und jede lodash-Funktion ist auch in einer eigenen _a la carte_ Bibliothek verfügbar. Es gibt keinen _funktionalen_ Vorteil für import { groupBy } from "lodash" über import groupBy from "group-by" . Warum sollte ich mich mit Tree-Shaking auseinandersetzen müssen, wenn ich nur das installieren kann, was ich brauche?

Aber die Erfahrung mit der Verwendung von Lodash unterscheidet sich grundlegend von der Verwendung von Rezepten oder Nanobibliotheken. Sie wissen, dass es wahrscheinlich eine Lodash-Funktion gibt, die es tut, wenn Sie etwas mit einem Array tun und das Gefühl haben, sich zu wiederholen. Sie müssen kein Rezept nachschlagen, Sie müssen nichts installieren – wahrscheinlich müssen Sie nicht einmal eine weitere Importzeile zur Datei hinzufügen. Es beseitigt nur die kleinste Menge an Reibung, aber unsere Tage sind voller Momente wie diesem und es summiert sich.

Ich hoffe, es macht Ihnen nichts aus, dass ich meine eigenen 2 Cent aus einer anderen Perspektive hinzufüge.

Die Denkschulen von CQRS , Event Sourcing und letztendlich Domain Driven Design sind die größeren Vorfahren , die uns Flux und Redux langweilten . Während diese Einflüsse gelegentlich zitiert werden , haben Redux und seine Nachkommen-Tools den größten Teil ihrer API-Terminologie von Flux- und Flux- Implementierungen, die zu dieser Zeit populär waren, übernommen. Das ist in Ordnung, aber ich denke, wir verpassen eine Gelegenheit, von der bestehenden Belichtung zu profitieren, die Entwickler von diesen Ideen hatten.

Um zwei Beispiele für den Unterschied zu nennen: In den meisten Diskussionen über Event Sourcing , die ich gesehen habe, werden Redux-Aktionen als Events bezeichnet . Redux ActionCreators werden als Commands bezeichnet . Ich denke, dass diese Terminologie auch etwas mehr Klarheit und Semantik bietet. Ereignisse sind protokollierbare, serialisierbare Daten. Ereignisse beschreiben, was in der Vergangenheitsform passiert ist. Ereignisse können wiederholt werden. Ereignisse können nicht rückgängig gemacht werden. Befehle haben eine zwingende Stimmung. Befehle lösen Ereignisse aus .

Ich vermute, dass Event Sourcing als Architekturmuster in den nächsten zehn Jahren an Popularität gewinnen wird, und ich denke, dass Redux Benutzerfreundlichkeit, Klarheit und Benutzerfreundlichkeit gewinnen könnte, indem die API und die Diskussion enger mit der breiteren Community ausgerichtet werden.

Ich glaube, diese Diskussion war schon totgeschlagen: https://github.com/reactjs/redux/issues/351

Oh, das war mir nicht bewusst, danke! :+1:

Es sieht so aus, als ob #351 geschlossen wurde, weil zu diesem Zeitpunkt keine Maßnahmen ergriffen werden konnten. Wenn wir an einem Punkt angelangt sind, an dem wir API-Entscheidungen und die von uns verwendete Sprache überdenken, scheint mir dies ein geeigneter Zeitpunkt zu sein, um die Idee erneut auf den Markt zu bringen.

Ich kann konkreter sein.

Hier ist meine Vorstellung davon, wie eine von Event Sourcing- Idiomen inspirierte API aussehen könnte:

Konzepte

  • Beobachtbarer Ereignisstrom
  • Event Stream verfügt über einen gut typisierten Satz unterstützter Events
  • Befehle, die an den Ereignisstrom gesendet werden
  • Ein oder mehrere Clients konsumieren den Event Stream

API

import { createEventStream, createProjection } from 'redux';

// Initialize the event stream separately from the store.  This becomes the one
// true source of truth for your application.
const eventStream = createEventStream({
  // Commands are the only thing that we want to couple to the eventStream.  The 
  // set of events which may end up in an eventStream should be easy to predict.
  //
  // A definition like this supports static analysis inference well for 
  // consumers that can leverage it.
  increment: () => ({ type: 'INCREMENT' }),
  decrement: () => ({ type: 'DECREMENT' }),
});

// Multiple stores with disjoint or overlapping data can be used to consume the 
// same event stream.
const store = createProjection(eventStream, reducer, init);
const adminStore = createProjection(eventStream, adminReducer, init);

// We don't need a jargon term ("Middleware"), or a dedicated hook to handle 
// async anymore.  We just register more subscribers to the eventStream.
eventStream.subscribe(myCustomMiddleWare);
eventStream.subscribe(sendEventsToAnalytics);
eventStream.subscribe(logEventsForPlayback);

// Calls to commands can be wrapped with React Providers or container components 
// in the same way that Redux currently does.  They can also be called directly.
eventStream.increment();

@ajhyndman :

(Auch wenn ich keine Statistiken habe, um dies zu belegen, würde ich vermuten, dass zu diesem Zeitpunkt mehr Leute mit der Verwendung von "Aktionen" und "Aktionserstellern" durch Redux vertraut sind als mit der CQRS / ES-Terminologie, zumindest innerhalb der JS-Community. )

Ich habe definitiv den Eindruck, dass dieses Gespräch schon einmal geführt wurde, und es besteht der starke Wunsch, es nicht wieder zu eröffnen. 😄 Ich werde hier nicht zu viel stärker drücken. (Ich wäre daran interessiert, dieses Gespräch an anderer Stelle zu lesen oder fortzusetzen, wenn es einen besseren Kontaktpunkt gibt.)

Sie haben natürlich auch Recht, dass es einen Verankerungsfaktor gibt und eine Änderung der gesamten API-Oberfläche und Terminologie zu diesem Zeitpunkt kostspielig wäre.

Ich würde immer noch argumentieren, dass es für die Event Sourcing- und Redux- Community die Möglichkeit gibt, voneinander zu lernen.

  • Welche möglichen Abstraktionen könnten erstellt werden, die den Lern- und Nutzungsprozess vereinfachen, ohne jedoch Redux tatsächlich zu verstecken (und würde hoffentlich einen Migrations-/Lernpfad zu "Basis" Redux bieten)?

Auch ohne die Terminologie auszuleihen oder die API zu ändern, denke ich, dass wir Gewinne erzielen können. Zum Beispiel habe ich Erfolg gehabt, Leute in Redux einzuführen, indem ich einen Store als "einen Zustandscontainer, in dem currentState eine "reine Funktion" ist (es ist abgeleitet oder reduziert von) einer Nur-Anhänge-Liste (oder einem Stream) beschreibe. von Aktionen".

Mit Blick in die Zukunft denke ich, dass es durchaus möglich ist, eine Redux-ähnliche Server-Infrastruktur zu implementieren und zu abstrahieren (siehe: Apache Samza und einige der anderen Arbeiten des Engineering-Teams von LinkedIn). Wenn wir das anstreben, dann sollte es auch möglich sein, ähnliche Abstraktionen für das Client- und Server-Zustandsmanagement zu verwenden! Wenn wir das erreichen können, warum dann nicht ein isomorpher, persistenter Redux- Speicher?

Jegliche Konzepte, auf denen die JavaScript- und Infrastruktur-Communitys zusammenkommen oder die sie leicht abbilden können, desto schneller erwarte ich, dass diese Möglichkeiten offensichtlich werden und desto ausdrucksvoller die Abstraktionen.

Ich glaube, ich bin gerade ein wenig aufgeregt über einige dieser Ideen! Ich hoffe, Sie verzeihen mir das Wort Dump.

Randnotiz: Es scheint möglich zu sein, eine Event-Stream-ähnliche Wrapper-API für Redux zu erstellen, die die oben vorgeschlagene Oberfläche implementiert!

https://github.com/ajhyndman/redux-event-stream

@ajhyndman Ich denke, der Wrapper ist der richtige Weg zu deiner Idee dort

In Bezug auf die von Ihnen erwähnte Samza- und Linkedin-Engineering-Arbeit: Wenn andere den wunderbaren Vortrag Die Datenbank mit Apache Samza auf den Kopf stellen nicht gelesen/angesehen

Dieses Video ist großartig! Es ist auch tatsächlich der zweite Punkt in der Liste des Dankes an dem redux README Repo.

Hallo allerseits!

Ohne mir der Existenz dieses Threads bewusst zu sein, habe ich eine Bibliothek entwickelt, die in gewisser Weise eine direkte Antwort auf die ursprünglichen Fragen von @markerikson ist und die meisten Dinge aus der Liste von @gaearon streicht .

Die Bibliothek heißt Kea :

screen shot 2017-08-06 at 13 10 03

Es ist eine Abstraktion über Redux, Redux-Saga und Reselect. Abgesehen von dem Klebstoff, der sie miteinander verbindet, gibt Kea nicht vor, etwas Neues zu schaffen, und enthüllt nach Bedarf rohe Redux-Action-Ersteller und -Reduzierer, rohe Redux-Saga-Sagas und rohe Reselect-Selektoren. Es erfindet kein neues Konzept.

Kea unterstützt viele verschiedene Betriebsmodi: Sie können es eigenständig verwenden, mit React-Komponenten verbunden, über React-Komponenten integriert oder sogar dynamisch mit React-Komponenten verbunden, wobei die Eingabe in die Selektoren von den Requisiten der React-Komponente abhängt.

Ich persönlich nutze es mit zwei großen Anwendungen: einem Marktplatz für Privatunterricht und einer riesigen Flottenverfolgungssoftware. Außerdem kenne ich Leute, die ihre eigenen Apps damit gebaut haben. Weil es für uns so nützlich war, habe ich viel Zeit damit verbracht, es aufzuräumen und Dokumentationen zu schreiben.

Für mich hat diese Bibliothek immer die Boilerplate stark reduziert, während sie dem Kern von Redux selbst treu geblieben ist.

Wie auch immer, genug geredet, hier ist etwas Code. Dies ist ein Beispiel für das, was ich "Inline-Kea" nenne - bei dem die Logik direkt an Ihre Komponente angehängt wird. Dieser Modus ist ideal, wenn Sie gerade erst anfangen oder als Alternative zu Reacts setState .

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { kea } from 'kea'

@kea({
  actions: () => ({
    increment: (amount) => ({ amount }),
    decrement: (amount) => ({ amount })
  }),

  reducers: ({ actions }) => ({
    counter: [0, PropTypes.number, {
      [actions.increment]: (state, payload) => state + payload.amount,
      [actions.decrement]: (state, payload) => state - payload.amount
    }]
  }),

  selectors: ({ selectors }) => ({
    doubleCounter: [
      () => [selectors.counter],
      (counter) => counter * 2,
      PropTypes.number
    ]
  })
})
export default class Counter extends Component {
  render () {
    const { counter, doubleCounter } = this.props
    const { increment, decrement } = this.actions

    return (
      <div className='kea-counter'>
        Count: {counter}<br />
        Doublecount: {doubleCounter}<br />
        <button onClick={() => increment(1)}>Increment</button>
        <button onClick={() => decrement(1)}>Decrement</button>
      </div>
    )
  }
}

Falls Ihre App wächst und mehr Orte Zugriff auf die Aktionen increment und decrement oder die Requisite counter benötigen, können Sie Ihren Code einfach wie folgt aufteilen:

// counter-logic.js
import PropTypes from 'prop-types'
import { kea } from 'kea'

export default kea({
  actions: () => ({
    increment: (amount) => ({ amount }),
    decrement: (amount) => ({ amount })
  }),

  reducers: ({ actions }) => ({
    counter: [0, PropTypes.number, {
      [actions.increment]: (state, payload) => state + payload.amount,
      [actions.decrement]: (state, payload) => state - payload.amount
    }]
  }),

  selectors: ({ selectors }) => ({
    doubleCounter: [
      () => [selectors.counter],
      (counter) => counter * 2,
      PropTypes.number
    ]
  })
})
// index.js
import React, { Component } from 'react'
import { connect } from 'kea'

import counterLogic from './counter-logic'

@connect({
  actions: [
    counterLogic, [
      'increment',
      'decrement'
    ]
  ],
  props: [
    counterLogic, [
      'counter',
      'doubleCounter'
    ]
  ]
})
export default class Counter extends Component {
  render () {
    const { counter, doubleCounter } = this.props
    const { increment, decrement } = this.actions

    return (
      <div className='kea-counter'>
        Count: {counter}<br />
        Doublecount: {doubleCounter}<br />
        <button onClick={() => increment(1)}>Increment</button>
        <button onClick={() => decrement(1)}>Decrement</button>
      </div>
    )
  }
}

Bitte probieren Sie es aus und lesen Sie die Dokumentation , um mehr über Nebenwirkungen von Redux-Saga und andere Funktionen zu erfahren, die Sie verwenden können.

Das Feedback für Kea war bisher überwältigend positiv und zitierte aus einem Problem : "Mehr Leute sollten KeaJS verwenden, um die Redux-Welt zu einem besseren Ort zu machen! 👍" :)

Vielen Dank für Ihre Zeit und dass Sie bis hierhin gelesen haben! :)

Sieht gut aus! mag die magischen Saiten aber nicht wirklich 'increment'

Ist diese Diskussion an einer anderen Stelle vorangekommen? Ist Kea das korrekteste Ergebnis, das allgemein akzeptiert wird?

@lucfranken : nein, die Diskussion ist verpufft.

Wenn Sie nach einer Abstraktion auf höherer Ebene über Redux suchen, ist Kea wahrscheinlich eine gute Option. Wenn Sie nach einem "Redux-Starterpaket" suchen, das den Einrichtungsprozess des Stores vereinfacht, müssen Sie sich möglicherweise etwas umschauen. Ich weiß, dass ich solche Dinge in freier Wildbahn gesehen habe, aber wir haben im Moment keine offizielle Bibliothek wie diese.

Ich werfe meinen Hut hier in den Ring. So adressiere ich dieses Problem: https://github.com/HenrikJoreteg/redux-bundler

Ich persönlich denke, es ist eine große Vereinfachung und Reduzierung von Boilerplate.

So habe ich alles gebaut, was ich in letzter Zeit gebaut habe.

Hey, in meiner Firma haben wir gerade eine Bibliothek als Open Source geöffnet, die die Netzwerkschicht verwaltet und viele Boilerplates aus Redux entfernt. Bei uns hat es sich bewährt, aber probiert es selbst aus: https://github.com/Brigad/redux-rest-easy/ (mittlerer Artikel: https://engineering.brigad.co/introducing-redux-rest-easy -6e9a91af4f59)

1_327nnvo3cuaqc-dsqpoq7w

Hier ist mein Ansatz zur Reduzierung der Redux-Boilerplate
image

https://github.com/zhDmitry/restate

Als sehr verspätete Necroing des Threads habe ich vor einiger Zeit auf Twitter um Feedback gebeten, was "Boilerplate" für die Leute bedeutet:

https://twitter.com/acemarke/status/969040835508604929

Rückkehr des Nekro-Threads!

Gemäß meiner Bearbeitung des ersten Kommentars in diesem Thread wurden die hier besprochenen Ideen in unser Redux-Starter-Kit-Paket umgewandelt . Bitte probieren Sie es aus und sehen Sie, wie sehr es Ihre Redux-Nutzung vereinfachen kann!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

ramakay picture ramakay  ·  3Kommentare

jbri7357 picture jbri7357  ·  3Kommentare

CellOcean picture CellOcean  ·  3Kommentare

elado picture elado  ·  3Kommentare

rui-ktei picture rui-ktei  ·  3Kommentare