Ich bin neu bei React / Redux. Ich verwende eine Fetch-API-Middleware in der Redux-App, um die APIs zu verarbeiten. Es ist ( Redux-API-Middleware ). Ich denke, es ist der gute Weg, um asynchrone API-Aktionen zu verarbeiten. Aber ich finde einige Fälle, die nicht von mir selbst gelöst werden können.
Wie auf der Homepage ( Lifecycle ) angegeben, beginnt ein Abruf-API-Lebenszyklus mit dem Versenden einer CALL_API-Aktion und endet mit dem Versenden einer FSA-Aktion.
Mein erster Fall ist also das Ein- / Ausblenden eines Preloaders beim Abrufen von APIs. Die Middleware sendet zu Beginn eine FSA-Aktion und am Ende eine FSA-Aktion. Beide Aktionen werden von Reduzierern empfangen, die nur eine normale Datenverarbeitung durchführen sollten. Keine UI-Operationen, keine Operationen mehr. Vielleicht sollte ich den Verarbeitungsstatus im Status speichern und ihn dann beim Aktualisieren des Speichers rendern.
Aber wie geht das? Ein Reaktionskomponentenfluss über die gesamte Seite? Was passiert mit der Aktualisierung des Geschäfts aufgrund anderer Aktionen? Ich meine, sie sind eher Ereignisse als Staaten!
Was soll ich tun, wenn ich den nativen Bestätigungsdialog oder den Warndialog in Redux / React-Apps verwenden muss? Wo sollen sie platziert werden, Maßnahmen oder Reduzierungen?
Die besten Wünsche! Wunsch für eine Antwort.
quelle
Antworten:
Das würde ich nicht sagen. Ich denke, Ladeindikatoren sind ein großartiger Fall der Benutzeroberfläche, der leicht als Funktion des Zustands beschrieben werden kann: in diesem Fall einer booleschen Variablen. Obwohl diese Antwort richtig ist, möchte ich einen Code bereitstellen, der dazu passt.
Im
async
Beispiel in Redux Repo aktualisiert derisFetching
Reduzierer ein Feld mit dem Namen :Die Komponente verwendet
connect()
React Redux, um den Status des Geschäfts zu abonnieren, und gibtisFetching
als Teil desmapStateToProps()
Rückgabewerts zurück, sodass er in den Requisiten der verbundenen Komponente verfügbar ist:Schließlich werden die Komponente Anwendungen
isFetching
prop in derrender()
Funktion eines „Loading ...“ Label zu machen (die möglicherweise ein Spinner statt sein könnte):Nebenwirkungen (und das Anzeigen eines Dialogs ist mit Sicherheit eine Nebenwirkung) gehören nicht zu den Reduzierern. Stellen Sie sich Reduzierer als passive „Staatsbauer“ vor. Sie "tun" nicht wirklich Dinge.
Wenn Sie eine Warnung anzeigen möchten, tun Sie dies entweder von einer Komponente aus, bevor Sie eine Aktion auslösen, oder von einem Aktionsersteller. Zum Zeitpunkt des Versands einer Aktion ist es zu spät, um als Reaktion darauf Nebenwirkungen auszuführen.
Für jede Regel gibt es eine Ausnahme. Manchmal ist Ihre Nebenwirkungslogik so kompliziert, dass Sie sie entweder an bestimmte Aktionstypen oder an bestimmte Reduzierungen koppeln möchten . In diesem Fall sehen Sie sich fortgeschrittene Projekte wie Redux Saga und Redux Loop an . Tun Sie dies nur, wenn Sie mit Vanille Redux vertraut sind und ein echtes Problem mit vereinzelten Nebenwirkungen haben, die Sie besser handhaben möchten.
quelle
Promise.all
zu einem einzigen Versprechen zusammenfassen und dann eine einzige Aktion für alle Abrufe auslösen. Oder Sie müssen mehrereisFetching
Variablen in Ihrem Status verwalten.isFetching
Flagge. Es wird für jede Gruppe von Objekten festgelegt, die abgerufen werden. Sie können die Reduziererzusammensetzung verwenden, um dies zu implementieren.RECEIVE_POSTS
bleibt , wenn die Anforderung fehlschlägt und niemals ausgelöst wird, es sei denn, Sie haben eine Zeitüberschreitung zumerror loading
Anzeigen einer Nachricht erstellt.Tolle Antwort Dan Abramov! Ich möchte nur hinzufügen, dass ich mehr oder weniger genau das in einer meiner Apps getan habe (isFetching als Booleschen Wert beibehalten) und es schließlich zu einer Ganzzahl machen musste (die letztendlich als Anzahl der ausstehenden Anforderungen gelesen wird), um mehrere gleichzeitig zu unterstützen Anfragen.
mit boolean:
Anfrage 1 startet -> Spinner ein -> Anfrage 2 startet -> Anfrage 1 endet -> Spinner aus -> Anfrage 2 endet
mit Ganzzahl:
Anfrage 1 startet -> Spinner ein -> Anfrage 2 startet -> Anfrage 1 endet -> Anfrage 2 endet -> Spinner aus
quelle
isFetching
Flag. Wenn Sie sich das Beispiel, auf das ich verlinkt habe, genau ansehen, werden Sie feststellen, dass es nicht ein Objekt mit,isFetched
sondern viele gibt: eines pro Subreddit (was in diesem Beispiel abgerufen wird).fetchCounter
Fortschrittsbalken für einige Fortschrittsbalken am oberen Bildschirmrand als auch mehrere spezifischeisFetching
Flags für Listen und Seiten haben.Ich möchte etwas hinzufügen. Im Beispiel der realen Welt wird ein Feld
isFetching
im Geschäft verwendet, um darzustellen, wann eine Sammlung von Elementen abgerufen wird. Jede Sammlung wird auf einenpagination
Reduzierer verallgemeinert, der mit Ihren Komponenten verbunden werden kann, um den Status zu verfolgen und anzuzeigen, ob eine Sammlung geladen wird.Mir ist passiert, dass ich Details für eine bestimmte Entität abrufen wollte, die nicht in das Paginierungsmuster passt. Ich wollte einen Status haben, der darstellt, ob die Details vom Server abgerufen werden, aber ich wollte auch keinen Reduzierer dafür haben.
Um dies zu lösen, habe ich einen weiteren generischen Reduzierer namens hinzugefügt
fetching
. Es funktioniert in ähnlicher Weise wie die Paginierung Minderer und es liegt in der Verantwortung nur zu beobachten , eine Reihe von Aktionen und neuen Zustand mit Paaren zu erzeugen[entity, isFetching]
. Auf diese Weise kannconnect
der Reduzierer auf jede Komponente zugreifen und feststellen, ob die App derzeit Daten nicht nur für eine Sammlung, sondern für eine bestimmte Entität abruft.quelle
Ich bin auf diese Frage bis jetzt nicht gestoßen, aber da keine Antwort akzeptiert wird, werde ich meinen Hut hineinwerfen. Ich habe genau für diesen Job ein Tool geschrieben: React-Loader-Factory . Es ist etwas mehr los als Abramovs Lösung, aber es ist modularer und praktischer, da ich nach dem Schreiben nicht nachdenken musste.
Es gibt vier große Stücke:
const loaderWrapper = loaderFactory(actionsList, monitoredStates);
connect()
in Redux zurückgegeben wird), sodass Sie sie einfach an Ihre vorhandenen Materialien anschrauben können.const LoadingChild = loaderWrapper(ChildComponent);
ACTION_SUCCESS
undACTION_REQUEST
). (Sie können Aktionen auch an eine andere Stelle senden und natürlich nur vom Wrapper aus überwachen, wenn Sie möchten.)Das Modul selbst ist unabhängig von Redux-API-Middleware, aber damit verwende ich es. Hier ist ein Beispielcode aus der README-Datei:
Eine Komponente mit einem Loader, der sie umschließt:
Ein Reduzierer, den der Loader überwachen kann (obwohl Sie ihn auch anders verkabeln können , wenn Sie möchten):
Ich gehe davon aus, dass ich in naher Zukunft dem Modul Dinge wie Timeout und Fehler hinzufügen werde, aber das Muster wird nicht sehr unterschiedlich sein.
Die kurze Antwort auf Ihre Frage lautet:
quelle
Bin ich der einzige, der denkt, dass Ladeindikatoren nicht in einen Redux-Store gehören? Ich meine, ich glaube nicht, dass es per se Teil des Status einer Anwendung ist.
Jetzt arbeite ich mit Angular2 und habe einen "Ladedienst", der verschiedene Ladeindikatoren über RxJS BehaviourSubjects anzeigt. Ich denke, der Mechanismus ist der gleiche, ich speichere die Informationen einfach nicht in Redux.
Benutzer des LoadingService abonnieren nur die Ereignisse, die sie abhören möchten.
Meine Redux-Aktionsersteller rufen den LoadingService auf, wenn sich etwas ändern muss. UX-Komponenten abonnieren die exponierten Observablen ...
quelle
Sie können Ihren Filialen Änderungslistener hinzufügen, indem Sie entweder
connect()
React Redux oder die Low-Level-store.subscribe()
Methode verwenden. Sie sollten die Ladeanzeige in Ihrem Geschäft haben, die der Handler für Geschäftsänderungen dann überprüfen und den Komponentenstatus aktualisieren kann. Die Komponente rendert dann den Preloader bei Bedarf basierend auf dem Status.alert
undconfirm
sollte kein Problem sein. Sie blockieren und der Alarm nimmt nicht einmal Eingaben vom Benutzer entgegen. Mitconfirm
können Sie den Status basierend auf dem Klick des Benutzers festlegen, wenn die Benutzerauswahl das Rendern von Komponenten beeinflussen soll. Wenn nicht, können Sie die Auswahl als Komponentenelementvariable für die spätere Verwendung speichern.quelle
addNofication(message)
. Ein weiterer Fall sind die Preloader, die ebenfalls von der nativen Host-App bereitgestellt und von ihrer Javascript-API ausgelöst werden. Ich füge einen Wrapper für diese API incomponentDidUpdate
einer React-Komponente hinzu. Wie entwerfe ich die Requisiten oder den Status dieser Komponente?Wir haben drei Arten von Benachrichtigungen in unserer App, die alle als Aspekte konzipiert sind:
Alle drei befinden sich auf der obersten Ebene unserer App (Main) und werden über Redux verkabelt, wie im folgenden Codeausschnitt gezeigt. Diese Requisiten steuern die Anzeige ihrer entsprechenden Aspekte.
Ich habe einen Proxy entworfen, der alle unsere API-Aufrufe verarbeitet. Daher werden alle isFetching- und (API-) Fehler mit actionCreators vermittelt, die ich in den Proxy importiere. (Nebenbei benutze ich auch Webpack, um einen Mock des Backing-Service für Entwickler einzufügen, damit wir ohne Serverabhängigkeiten arbeiten können.)
Jeder andere Ort in der App, der irgendeine Art von Benachrichtigung bereitstellen muss, importiert einfach die entsprechende Aktion. Snackbar & Error haben Parameter für die Anzeige von Nachrichten.
) Export Standardklasse Main erweitert React.Component {
quelle
Ich speichere die URLs wie ::
Und dann habe ich einen gespeicherten Selektor (über Reselect).
Um die URL im Falle eines POST eindeutig zu machen, übergebe ich eine Variable als Abfrage.
Und wo ich einen Indikator anzeigen möchte, verwende ich einfach die Variable getFetchCount
quelle
Object.keys(items).filter(item => items[item] === true).length > 0 ? true : false
durch ersetzenObject.keys(items).every(item => items[item])
.some
stattdessenevery
, aber ja, zu viele nicht benötigte Vergleiche in der ersten vorgeschlagenen Lösung.Object.entries(items).some(([url, fetching]) => fetching);