Christian Kruse: Frage zu REACT

Beitrag lesen

Hallo heinetz,

Als meine Komponente grösser wurde hatte ich angefangen, Kind-Komponenten auszulagern. Dann kam ich an den Punkt, dass die übereinander Bescheid wissen und miteinander kommunizieren müssen.

Ja, das ist ein typischer Verlauf 😀

Dann bin ich auf die Context-Api gestossen, die mir genau diese Möglichkeit gegeben hat.

Mit ...

<MwocAppContext.Provider value={this}>

... habe ich in den Kindkomponenten sämtliche Informationen über die Elternkomponente zu Verfügung. Offenbar ist das problematisch und ich bin bereit, Deinem Ratschlag zu folgen, wenn ich verstanden habe, warum mein Weg nicht der richtige ist.

Du hast mich missverstanden (oder ich habe mich missverständlich ausgedrückt). Ich habe nicht sagen wollen, dass dein Ansatz falsch ist – er funktioniert ja offensichtlich. Aber er hat Nachteile. Eine der Prinzipien von React ist, dass man seine Komponenten voneinander isoliert und so wenig wie möglich miteinander koppelt. Damit wird der Code einfacher bzw überhaupt erstmal testbar und die Komplexität wird reduziert.

Der Gedanke ist, dass deine Komponenten einzelne „Inseln“ darstellen, mit klaren APIs (über die Proptypes), und nur über diese APIs kommuniziert wird. Dadurch kannst du innerhalb deiner Komponenten die Komplexität auf das Teilproblem reduzieren, die Abhängigkeiten untereinander schrumpfen und der Code wir übersichtlicher und testbar. Alles gute Dinge.

Wenn du jetzt deine komplette Klasse (und nicht nur den State) über einen Kontext teilst, dann kannst du die Unterteilung in einzelne Komponenten auch fast lassen. Du stellst die größtmögliche Abhängigkeit her zwischen den einzelnen Komponenten, nix mehr mit loose coupling. Wenn ich etwas in einer Kind-Komponente ändern will, muss ich gleichzeitig die Eltern-Komponente verstehen und im Kopf haben sowie alle Geschwister-Komponenten. Und auch testen wird dadurch ziemlich schwierig: wie willst du die einzelnen Komponenten unabhängig voneinander testen?

Um dein Problem zu lösen gibt es verschiedene Ansätze. Ein Ansatz wäre es Render-Props und Callback-Funktionen zu nutzen, die ein Ereignis kommunizieren und so den State deiner Eltern-Komponente ändern und mitteilen, z.B. sowas:

import React, { useState } from "react";

function CounterButton(props) {
  return <p><button onClick={ev => props.onClick()} /></p>;
}

function CounterDisplay(props) {
  return <p>{props.counter} mal geklickt.</p>;
}

function Parent(props) {
  const [counter, setCounter] = useState(0);
  return (
    <div>
      <CounterDisplay counter={counter} />
      <CounterButton onClick={() => setCounter(counter + 1)} />
    </div>
  );
}

In diesem (sehr simplen) Beispiel haben die beiden Kind-Komponenten keine Abhängigkeiten voneinander und sind sehr einfach testbar. Ihr Zweck und ihre API ist klar erkennbar.

Ein anderer Weg wäre eine Flux-Architektur etwa mit Redux, bei dem es (fast) keinen lokalen State mehr gibt. Aber auch da gilt: je mehr du in die Stores der anderen Komponenten reingreifst, desto mehr Abhängigkeiten schaffst du zwischen den Komponenten.

Vielleicht hilft dir auch Event-Bubbling.

Ich kann dir leider nicht mehr sagen als diese allgemeinen Hinweise, da ich deine Aufgabe und deinen Code nicht kenne.

LG,
CK