web-dev-qa-db-de.com

So synchronisieren Sie Redux-Status- und URL-Abfrageparameter

Ich habe eine Webseite mit einem Suchfeld. Suchfeld hat mehrere Eingabefelder: ID, Größe, ...

Was ich möchte, ist, wenn der Benutzer Suchwerte (zum Beispiel: id = 123 und size = 45) einstellt und eine Suchschaltfläche drückt:

  1. searchState in Redux Reducer sollte mit neuen Suchwerten aktualisiert werden (ID = 123 und Größe = 45)
  2. Die URL sollte in " http: // meineDomäne/home? Id = 123 & size = 45 " geändert werden.

Und auf der anderen Seite, wenn der Benutzer die URL in http: // meineDomäne/home? Id = 111 & size = 22 ändert, dann:

  1. searchState im Reduzierer sollte mit neuen Suchwerten geändert werden (id = 111 und size = 22)
  2. Eingaben im Suchfeld der Benutzeroberfläche sollten mit neuen Werten aktualisiert werden (ID = 111 und Größe = 22)

Wie erreiche ich mit dem Ziel? Welchen Router soll ich verwenden (React-Router, Redux-Router, React-Router-Redux usw.)?

61
Anton

Ich würde nur vorschlagen, React Router direkt zu verwenden und nicht searchState in Redux zu behalten. React Der Router fügt URL-Parameter in Ihre Komponenten ein und Sie können sie in mapStateToProps(state, ownProps) verwenden, um die endgültigen Requisiten zu berechnen.

Wenn Sie Routenänderungen wirklich als Aktionen sehen möchten, können Sie react-router-redux für die bidirektionale Synchronisierung verwenden, aber es werden Ihnen nicht die Parameter im Status angezeigt - nur der aktuelle Standort. Dies ist der einzige Anwendungsfall, wenn Sie Aktionen aufzeichnen und wiedergeben und die URL-Leiste aktualisieren möchten, während Sie sie wiedergeben.

Es ist keineswegs erforderlich - in den meisten Fällen reicht es aus, nur React Router direkt zu verwenden.

51
Dan Abramov

Kurz : Sie können redux-query-sync verwenden, um die URL-Parameter und -Felder im Store synchron zu halten. Es funktioniert ohne Router.


Längere Geschichte : Mit der gleichen Frage kämpfend, schätzte ich zuerst Dan Abramovs Antwort und schlug vor, (in meinen Worten) das zu betrachten URL als "zweiter Speicher", ein Teil des Anwendungsstatus außerhalb des Redux-Speichers. Aber dann stellte ich fest, dass zwei Arten von "Geschäften" es schwierig machen, Code zu modifizieren, z. Verschieben Sie Dinge von einem zum anderen, weil jedes "Geschäft" eine andere Oberfläche hat. Als Entwickler möchte ich lieber eines der Felder in meinem Redux-Status auswählen und diese in der URL anzeigen , als wäre der Speicherort ein kleines Fenster zu meinem Staat.

Daher habe ich gerade redux-query-sync veröffentlicht, damit Sie eine Auswahlfunktion zum Auswählen eines Werts aus dem Status bereitstellen können, der dann an der Fensterposition unter einem von Ihnen angegebenen Parameternamen angezeigt wird. Damit es auch in die andere Richtung synchronisiert wird, also vom URL zum Redux-Status (z. B. wenn die Anwendung zum ersten Mal geladen wird), können Sie einen Aktionsersteller angeben, dem der Parameterwert übergeben wird, damit Ihr Reduzierer den Status entsprechend aktualisieren kann.

12
Gerben

So habe ich mit dem ersten Szenario umgegangen:

  • Wenn sich der Eingabewert ändert, löst seine Komponente einen Rückruf aus, der als Requisite aus seinem Container übergeben wurde.

  • Im Rückruf löst der Container die Aktion aus, die für die Aktualisierung des Redux-Status beim Eintreten des Ereignisses verantwortlich ist.

  • In der Zeile unmittelbar nach dem Aktionsaufruf verwende ich this.context.router.Push() und übergebe ihm die URL mit der richtigen Abfragezeichenfolge.

Ich bin nicht sicher, ob dies der richtige Ansatz ist. Ich fand es vorzuziehen, die URL zuerst zu aktualisieren, da die Abfragezeichenfolge meiner Meinung nach eher ein Abbild des Status als des Masters sein sollte.

Bezüglich des umgekehrten Szenarios bin ich mir nicht sicher. Es scheint, als würde das manuelle Einstellen der URL ein vollständiges Neuladen auslösen, aber ich könnte mich irren.

Was den zu verwendenden Router betrifft, verwende ich React Router von selbst. Ich fand keinen Wert darin, die anderen zu verwenden, und diese Diskussion war der Drahtreifen für mich .

2
cantera

Ich habe vor kurzem ein ähnliches Problem bearbeitet. Ich habe MobX als meinen Store und Redux-Router als meinen Router benutzt. (Ich habe mit dem React-Router gut abgeschnitten, aber ich musste eine Push-Aktion außerhalb der Komponente auslösen - Redux als globaler Speicher funktioniert hier hervorragend.)

Meine Lösung ähnelte der von cantera beschriebenen - mein Router-Status spiegelt lediglich den Formularstatus wider. Dies hat den zusätzlichen Vorteil, dass ich meinen Formularstatus nicht verlieren muss und nur vom Router-Status abhängig bin.


Im ersten Szenario

1) Ich aktualisiere meine Formulareingabe wie gewohnt, wodurch ein erneutes Rendern in der Ergebniskomponente ausgelöst wird.

2) In componentDidUpdate() der Ergebniskomponente verwende ich die Formular-Requisiten, um die aktualisierte Abfragezeichenfolge zu erstellen.

3) Schieben Sie die aktualisierte Abfragezeichenfolge in den Router-Status. Dies dient lediglich der Aktualisierung der URL.


Für das zweite Szenario

1) In dem onEnter -Hook auf der Stammkomponente Route erhalte ich die verfügbare Abfragezeichenfolge und analysiere sie in die anfänglichen Formularwerte.

2) Ich aktualisiere meinen Shop mit den Werten. Dies gilt nur für das erste Laden der Seite und das einzige Mal, wenn der Router-Status den Formularstatus vorgibt.


Bearbeiten: Diese Lösung berücksichtigt den Fall nicht, wenn Sie in den Browserverlauf zurückkehren, da die URL Ihren Status nicht aktualisiert.

2
xiankai

Ich würde das neue Tool empfehlen react-url-query , mit dem die Synchronisierung ganz einfach durchgeführt werden kann.

1
Hearen