2017-01-09 2 views
3

Ich habe React + Redux + Typescript Anwendung bestehend aus einer Karte, mehrere Diagramme und eine Reihe von modalen Dialogen (von denen eine ist ein Druckformular). Die presentational and container components sind wie folgt zusammengesetzt.Wie übertrage ich eine reaktive Komponente sauber an eine andere Komponente in der Komponentenhierarchie?

┌──────────────────────────────────────────┐ 
│ app.tsx         │ 
│ ┌─────────────────────────────────────┐ │ 
│ │ modalsContainer.tsx     │ │ 
│ │ ┌────────────────────────────────┐ │ │ 
│ │ │ printModal.tsx     │ │ │ 
│ │ │ ┌───────────────────────────┐ │ │ │ 
│ │ │ │ printFormContainer.tsx │ │ │ │ 
│ │ │ │ const mergeProps(...); │ │ │ │ 
│ │ │ └───────────────────────────┘ │ │ │ 
│ │ └────────────────────────────────┘ │ │ 
│ └─────────────────────────────────────┘ │ 
│ ┌─────────────────────────────────────┐ │ 
│ │ mapContainer.tsx     │ │ 
│ │ ┌────────────────────────────────┐ │ │ 
│ │ │ map.tsx      │ │ │ 
│ │ │  private map:EsriMap  │ │ │ 
│ │ └────────────────────────────────┘ │ │ 
│ └─────────────────────────────────────┘ │ 
│ ┌─────────────────────────────────────┐ │ 
│ │ dashboard.tsx      │ │ 
│ │ ┌────────────────────────────────┐ │ │ 
│ │ │ charts.tsx      │ │ │ 
│ │ └────────────────────────────────┘ │ │ 
│ └─────────────────────────────────────┘ │ 
└──────────────────────────────────────────┘ 

Die Druckform ermöglicht es dem Benutzer, die Charts zu drucken und zu einer PDF-Karte. Eine Webanforderung wird erstellt, damit der Bericht basierend auf den ausgewählten Diagrammen und der aktuellen Karte gedruckt wird.

const mergeProps = (stateProps: any, dispatchProps: any, ownProps: any): any => { 
    return { 
     fetchReport: (title: string, summary: string, includeMap: boolean) => { 
      if(includeMap) { 
       // fetch map image 
       // need access to mapcontainer /map/esrimap here 
      } 

      // ... fetch report ... 
     }, 
     close: dispatchProps.close 
    }; 
}; 

Diese meist funktioniert, aber ich habe noch zählen das Kartenbild in dem Bericht: Die Logik für diese ist in const mergeProps(...); unten aufgebaut. Um ein Bild der Karte zu erzeugen, muss ich eine PrintTask ausführen. Einer der Parameter für die Druckaufgabe ist das Esri-Map-Objekt. Von mergeProps habe ich jedoch keinen Zugriff auf die MapContainer- oder Map-Komponenten. Wenn ich das täte, könnte ich eine Print():Promise<any> Funktion hinzufügen, um die Aufgabe durchzuführen und das Bild zurückzugeben.

Ich möchte wirklich Globals vermeiden. Andere Fähigkeiten in der Zukunft erfordern möglicherweise auch Zugriff auf die Karte. Ich möchte auch vermeiden, Komponenten als Requisiten so tief durch den Stapel zu führen. Ich lese ein wenig über context, aber das scheint nicht sehr zu empfehlen.

Wie übertrage ich eine Komponente tief in den Stapel hinein?

+0

Sie können die Komponente auf Ihren Redux-Zustand setzen und mit 'connect' greifen. react-redux verwendet den Kontext übrigens – azium

+0

Warum nicht einfach die Aktion PrintTask innerhalb Ihrer Map-Komponente auslösen, die Zugriff auf das EsirMap-Objekt hat. Übergeben Sie die Dispatch-Aktion in die Map-Komponente, damit Sie den Anwendungsstatus ändern können. – Gamak

+0

@Gamak, ich hatte das in Erwägung gezogen, aber trotzdem müsste die 'MapComponent' noch durch die Layer nach' mergeProps' weitergeleitet werden, um diese Funktion auszuführen. –

Antwort

2

Ein paar Gedanken:

Zuerst etwas nicht serialisierbaren (wie eine Komponente oder eine Funktion) in den Redux Zustand versetzt ist generell eine schlechte Idee (pro https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state).

Zweitens, warum ist die Callback-Logik derzeit in mergeProps definiert? Diese Option sollte wirklich nur ein Rückgriff auf den letzten Ausweg sein. Es ist besser Callbacks separat zu definieren und an die Komponente zu übergeben. Ich habe einige Diskussionen und Beispiele dazu unter http://blog.isquaredsoftware.com/2016/10/idiomatic-redux-why-use-action-creators/.

Ich glaube, der einfachste Ansatz wäre, eine separate Callback-Funktion zu definieren, die die benötigten Flags und das EsriMap-Objekt als Parameter übernimmt und diese Funktion als Prop zu der Map-Komponente übergibt.

+0

Die Logik befindet sich derzeit in 'mergeProps', um den' print report'-Button mit der 'fetchReport'-Funktion zu verbinden. Ich benötigte Zugriff auf einen bestimmten Status (z. B. als Liste der zu druckenden Diagramme), um eine Berichtswebanforderung zu generieren. Ich muss ein Kartenbild für die Anfrage erzeugen; Dies kann nur mit einer Druckaufgabe erfolgen, die 'map' als Parameter benötigt. 'MapContainer' ist jedoch nicht von meinem' printFormContainer' verfügbar. Ich brauche Zugriff auf den Zustand und eine Komponente an anderer Stelle im Komponentenbaum. FWIW, die Druckberichtfunktion ändert den Status nicht. Action-Ersteller werden normalerweise verwendet, um den Status zu ändern, richtig? –

+0

Als Alternative zu 'mergeProps' könnten Sie die Komponente die erforderlichen Daten in 'mapState' abrufen lassen, und dann den Wert von reps holen und an die externe Callback-Funktion übergeben. Sie könnten auch die Callback-Funktion/den Aktionsersteller als "Thunk" definieren, was ihm den Zugriff auf "getState()" ermöglicht. – markerikson

+0

Bleibt das ursprüngliche Problem nicht bestehen, das heißt, die Callback-Funktion hat immer noch keinen Zugriff auf den erforderlichen map-Parameter? –

Verwandte Themen