Ist Redux nicht nur ein verherrlichter globaler Staat?

83

Also habe ich vor einer Woche angefangen, React zu lernen, und bin unweigerlich auf das Problem des Zustands und der Art und Weise gekommen, wie Komponenten mit dem Rest der App kommunizieren sollen. Ich habe mich umgesehen und Redux scheint der Geschmack des Monats zu sein. Ich habe die gesamte Dokumentation durchgelesen und denke, dass dies eine ziemlich revolutionäre Idee ist. Hier sind meine Gedanken dazu:

Der Staat ist im Allgemeinen ziemlich böse und eine große Quelle von Fehlern in der Programmierung. Anstatt alles in Ihrer App zu verteilen, sagt Redux, warum nicht einfach alles in einem globalen Statusbaum konzentriert haben, für den Sie Aktionen ausgeben müssen, um Änderungen vorzunehmen. Klingt interessant. Alle Programme benötigen einen Status. Lassen Sie uns ihn also in einem unreinen Bereich speichern und nur von dort aus ändern, damit Fehler leicht aufgespürt werden können. Dann können wir auch einzelne Statuselemente deklarativ an React-Komponenten binden und sie automatisch neu zeichnen lassen, und alles ist schön.

Ich habe jedoch zwei Fragen zu diesem gesamten Design. Zum einen, warum muss der Staatsbaum unveränderlich sein? Angenommen, mir ist das Debuggen von Zeitreisen und das Hot-Reload egal und ich habe bereits das Rückgängigmachen / Wiederherstellen in meiner App implementiert. Es scheint einfach so umständlich, dies tun zu müssen:

case COMPLETE_TODO:
  return [
    ...state.slice(0, action.index),
    Object.assign({}, state[action.index], {
      completed: true
    }),
    ...state.slice(action.index + 1)
  ];

An Stelle von:

case COMPLETE_TODO:
  state[action.index].completed = true;

Ganz zu schweigen davon, dass ich ein Online-Whiteboard erstelle, um zu lernen, und jede Statusänderung kann so einfach sein wie das Hinzufügen eines Pinselstrichs zur Befehlsliste. Nach einer Weile (Hunderte von Pinselstrichen) kann das Duplizieren dieses gesamten Arrays extrem teuer und zeitaufwändig werden.

Ich bin mit einem globalen Statusbaum einverstanden, der unabhängig von der Benutzeroberfläche ist, die über Aktionen mutiert ist. Muss er jedoch wirklich unveränderlich sein? Was ist falsch an einer einfachen Implementierung wie dieser (sehr grober Entwurf. In 1 Minute geschrieben)?

var store = { items: [] };

export function getState() {
  return store;
}

export function addTodo(text) {
  store.items.push({ "text": text, "completed", false});
}

export function completeTodo(index) {
  store.items[index].completed = true;
}

Es ist immer noch ein globaler Zustandsbaum, der durch ausgegebene Aktionen mutiert, aber äußerst einfach und effizient ist.

Ryan Peschel
quelle
2
"Zum einen, warum muss der Staatsbaum unveränderlich sein?" --- dann müssen Sie einen Algorithmus bereitstellen, um festzustellen, ob sich Daten geändert haben. Es ist nicht möglich, es für eine beliebige Datenstruktur zu implementieren (wenn es veränderbar ist). Nehmen Sie immutablejsund verwenden Sie return state.setIn([action.index, 'completed'], true);, um Boilerplate zu reduzieren.
Zerkms
1
PS:return state.map(i => i.index == action.index ? {...i, completed: true} : i);
Zerkms

Antworten:

52

Ist Redux nicht nur ein verherrlichter globaler Staat?

Natürlich ist es das. Das Gleiche gilt jedoch für jede Datenbank, die Sie jemals verwendet haben. Es ist besser, Redux als In-Memory-Datenbank zu behandeln, von der Ihre Komponenten reaktiv abhängen können.

Die Unveränderlichkeit ermöglicht die Überprüfung, ob ein Teilbaum sehr effizient geändert wurde, da dies bis zu einer Identitätsprüfung vereinfacht wird.

Ja, Ihre Implementierung ist effizient, aber der gesamte virtuelle Dom muss jedes Mal neu gerendert werden, wenn der Baum irgendwie manipuliert wird.

Wenn Sie React verwenden, führt dies möglicherweise zu einem Unterschied zum tatsächlichen Dom und führt nur minimale stapeloptimierte Manipulationen durch, aber das vollständige Top-Down-Re-Rendering ist immer noch ineffizient.

Bei einem unveränderlichen Baum müssen zustandslose Komponenten nur prüfen, ob die Teilbäume, von denen sie abhängen, sich in ihren Identitäten von den vorherigen Werten unterscheiden, und wenn ja, kann das Rendern vollständig vermieden werden.

lorefnon
quelle
3
Ist das nicht ein bisschen vorzeitige Optimierung? Woher wissen wir auch, dass die Kosten für das ständige Duplizieren unveränderlicher Objekte geringer sind als das erneute Rendern des DOM (würde Reacts virtuelles DOM diese Kosten auch nicht stark mindern?)
Ryan Peschel,
3
Nun, GUI-Bibliotheken diese Art der Optimierung für eine lange Zeit (siehe: bitquabit.com/post/the-more-things-change ) Plus-Verwaltung einer unveränderlichen Datenstruktur ist nicht so kostspielig, wie Sie vielleicht denken - zum Beispiel, wenn ein Knoten Wird geändert, muss nur eine einzige Kette von Eltern verkettet werden - der Rest der Knoten bleibt davon unberührt. Wir duplizieren also nicht die gesamte Datenstruktur für jede Aktion - wir verwenden die nicht geänderten Unterkomponenten erneut, um eine neue Datenstruktur zu erstellen.
Lorefnon
4
Auch Reacts Virtual DOM ist keine dunkle Magie - Zitat aus React-Dokumenten: "Das Generieren der Mindestanzahl von Operationen zum Transformieren eines Baums in einen anderen ist ein komplexes und gut untersuchtes Problem. - Die Algorithmen nach dem Stand der Technik weisen eine Komplexität in der Reihenfolge auf von O (n3) wobei n die Anzahl der Knoten im Baum ist. "
Lorefnon
2
Der Grund, warum React in der Praxis eine viel bessere Leistung erbringen kann, ist folgender: React basiert auf Heuristiken - also: "Wenn Sie keine stabilen Schlüssel bereitstellen (z. B. mithilfe von Math.random ()), werden alle Unterbäume verwendet werden jedes Mal neu gerendert. Indem die Benutzer die Wahl haben, den Schlüssel zu wählen, haben sie die Möglichkeit, sich selbst in den Fuß zu schießen. " So wie Sie React durch die Bereitstellung stabiler Schlüssel unterstützen können, können Sie auch React durch die Bereitstellung unveränderlicher Datenrequisiten unterstützen.
Lorefnon
1
Informationen zu Ihrem Array von Pinselstrichen finden Sie unter: facebook.github.io/immutable-js/docs/#/List Zitieren aus Dokumenten: Listen werden nach indizierten dichten Sammlungen sortiert, ähnlich wie bei einem JavaScript-Array. Listen implementieren Deque mit effizientem Hinzufügen und Entfernen sowohl am Ende (Push, Pop) als auch am Anfang (Unshift, Shift).
Lorefnon