FP Alternative zum Polymorphismus in JavaScript / ReactJS

8

Ich arbeite gerade an einem ReactJS-Projekt, bei dem ich "wiederverwendbare" Komponenten erstellen muss, in denen einige der Methoden "überschrieben" werden müssen. In OOP würde ich Polymorphismus verwenden. Ich habe etwas gelesen und es scheint, dass der Konsens darin besteht, HoC / Komposition zu verwenden, aber ich kann nicht recht herausfinden, wie ich das erreichen kann. Ich denke, wenn ich nur ein ES6-Sample mit Komposition bekommen könnte, wäre es vielleicht einfacher, die Idee später an ReactJS anzupassen.

Unten ist ein ES6 OOP-Beispiel (ignoriere die Ereignisbehandlung, die nur zum Testen dient) von ziemlich genau dem, was ich in ReactJS erreichen möchte. Hat jemand eine Anleitung, wie man eine ReactJS-Komponente in eine HoC aufspaltet oder einfach nur demonstriert, wie ich die Zusammensetzung in ES6 basierend auf dem Beispiel verwenden würde?

%Vor% %Vor%

UPDATE: Obwohl meine ursprüngliche Frage bei FP war, denke ich, dass Renderrequisiten eine wirklich gute Lösung für mein Problem sind und vermeidet die HoC-Probleme.

    
Wancieho 11.11.2017, 00:07
quelle

3 Antworten

0

Die Antwort bezüglich Ihres Beispielcodes befindet sich in der Mitte / unten in diesem Beitrag.

Eine gute Möglichkeit, Reaction-Kompositionen zu erstellen, ist das Render-Callback-Muster , auch bekannt als Funktion als Kind. Der Hauptvorteil gegenüber HOCs besteht darin, dass Sie Komponenten dynamisch zur Laufzeit (z. B. in render) statt statisch zum Zeitpunkt des Autors erstellen können.

Unabhängig davon, ob Sie render-callback oder HOCs verwenden, besteht das Ziel bei der Komponentenzusammensetzung darin, wiederverwendbares Verhalten an andere Komponenten zu delegieren und diese Komponenten dann als Requisiten an die Komponente zu übergeben, die sie benötigt.

Abstraktes Beispiel:

Die folgende Delegator -Komponente verwendet das render-callback-Muster, um die Implementierungslogik an ein ImplementationComponent zu delegieren, das als Property übergeben wird:

%Vor%

Die verschiedenen Implementierungskomponenten würden wie folgt aussehen:

%Vor%

Später könnten Sie weitere untergeordnete Komponenten in der Delegator -Komponente nach demselben Kompositionsmuster verschachteln:

%Vor%

Die verschachtelte untergeordnete Komponente ermöglicht nun mehrere konkrete Implementierungen:

%Vor%

Antwort (Ihr Beispiel):

Wenn Sie das obige Kompositionsmuster auf Ihr Beispiel anwenden, restrukturiert die Lösung Ihren Code, geht jedoch davon aus, dass Folgendes zu tun ist:

  • erlaubt Variationen von Eingaben und deren Validierungslogik
  • Wenn der Benutzer eine gültige Eingabe sendet, dann tun Sie etwas Ajax

Erstens, um die Dinge einfacher zu machen, habe ich das DOM zu:

geändert %Vor%

Nun kann TransferComponent nur noch eine Schaltfläche anzeigen und etwas tun, wenn die Schaltfläche gedrückt wird und die Daten gültig sind. Es weiß nicht, welche Eingaben angezeigt werden oder wie die Daten validiert werden. Es delegiert diese Logik an das verschachtelte VaryingComponent .

%Vor%

Nun erstellen wir konkrete Implementierungen von VaryingComponent , um verschiedene Eingabe- und Validierungslogiken zu erstellen.

Die Nur-Benutzername-Implementierung:

%Vor%

Die Implementierung von Benutzername und Passwort:

%Vor%

Schließlich würde das Erstellen von Instanzen von TansferComponent wie folgt aussehen:

%Vor%     
bsapaka 13.11.2017, 21:54
quelle
0

Wenn Sie Ihre Frage lesen, ist es nicht klar, ob Sie sich auf Komposition oder Vererbung beziehen, aber es sind unterschiedliche OOP-Konzepte. Ich empfehle Ihnen, diesen Artikel anzusehen, wenn Sie nicht wissen der Unterschied zwischen ihnen.

Über Ihr spezifisches Problem mit React. Ich würde dir empfehlen, die Benutzerzusammensetzung zu versuchen, da es dir viel Flexibilität gibt, deine Benutzeroberfläche zu erstellen und Requisiten zu verteilen.

Wenn Sie mit React arbeiten, verwenden Sie wahrscheinlich bereits Komposition, wenn Sie Dialoge dynamisch füllen. Wie die React-Dokumentation zeigt:

%Vor%

Die Leute bei Facebook haben sehr anspruchsvolle UIs entwickelt und Tausende von Komponenten mit React erstellt und keinen guten Anwendungsfall für die Vererbung über die Komposition gefunden. Wie die Dokumentation sagt:

  

React verfügt über ein leistungsstarkes Kompositionsmodell, und wir empfehlen die Verwendung von Komposition anstelle von Vererbung, um Code zwischen Komponenten wiederzuverwenden.

Wenn Sie wirklich Vererbung verwenden möchten, ist ihre Empfehlung, dass Sie die Funktionalität, die Sie für Komponenten verwenden möchten, in ein separates JavaScript-Modul extrahieren. Die Komponenten können sie importieren und diese Funktion, das Objekt oder eine Klasse verwenden, ohne sie zu erweitern.

In dem von Ihnen bereitgestellten Beispiel würden zwei Funktionen in utils.js problemlos funktionieren. Siehe:

%Vor%

Sie können sie importieren und in Ihren Komponenten einfach verwenden.

    
Tiago Alves 13.11.2017 17:16
quelle
0

Das Nicht-React-FP-Beispiel

Zunächst einmal ist die Funktion in der Funktionalen Programmierung ein Bürger erster Klasse. Das bedeutet, dass Sie Funktionen wie Daten in OOP behandeln können (z. B. als Parameter übergeben, Variablen zuweisen usw.).

Ihr Beispiel camples Daten mit Verhalten in den Objekten. Um eine rein funktionale Lösung zu schreiben, wollen wir diese trennen .

  

Bei der Funktionalen Programmierung geht es im Wesentlichen darum, Daten vom Verhalten zu trennen.

Beginnen wir also mit isValid .

Funktional isValid

Es gibt ein paar Möglichkeiten, die Logik hier zu ordnen, aber wir gehen damit fort:

  1. Angabe einer Liste von IDs
  2. Alle IDs sind gültig, wenn keine ungültige ID existiert

Was in JS bedeutet:

%Vor%

Wir brauchen ein paar Hilfsfunktionen, um das zu erreichen:

%Vor%

Wir könnten das alles in einer Zeile schreiben, aber wenn wir es aufteilen, ist es etwas lesbarer. Damit haben wir nun eine generische Funktion, mit der wir isValid für unsere Komponenten bestimmen können!

%Vor%

Funktionale Darstellung

Ich habe ein wenig an isValid geschummelt, indem ich document benutzt habe. In der funktionalen Programmierung sollten Funktionen pur sein. Oder, mit anderen Worten, das Ergebnis eines Funktionsaufrufs muss nur aus seinen Eingaben bestimmt werden (alias es ist ipotent) und es kann nicht Nebenwirkungen .

Wie also rendern wir mit dem DOM ohne Nebenwirkungen? Nun, React verwendet ein virtuelles DOM (eine ausgeklügelte Datenstruktur, die im Speicher verweilt und in Funktionen übergeben wird und von diesen zurückgegeben wird, um die Funktionsreinheit aufrechtzuerhalten) für die Kernbibliothek. Die Nebenwirkungen von React befinden sich in der react-dom -Bibliothek.

Für unseren Fall verwenden wir ein super einfaches virtuelles DOM (vom Typ string ).

%Vor%

Dies sind unsere Komponenten - um die React-Terminologie zu verwenden - die wir in UIs zusammenfassen können:

%Vor%

Dies scheint wahrscheinlich eine Vereinfachung zu sein und überhaupt nicht funktional. Aber der Operator + ist tatsächlich funktionsfähig! Denke darüber nach:

  • es braucht zwei Eingaben (der linke und der rechte Operand)
  • gibt ein Ergebnis zurück (für Strings die Verkettung der Operanden)
  • es hat keine Nebenwirkungen
  • es mutiert nicht seine Eingaben (das Ergebnis ist eine neue Zeichenkette - die Operanden sind unverändert)

Also, render ist jetzt funktionsfähig!

Was ist mit Ajax?

Leider können wir keinen Ajax-Aufruf durchführen, das DOM mutieren, Event-Listener einrichten oder Timeouts ohne Nebenwirkungen festlegen. Wir könnten den komplexen Weg der Erstellung von Monaden für diese Aktionen gehen, aber für unsere Zwecke genügt es zu sagen, dass wir nur die nicht-funktionalen Methoden verwenden werden.

Anwenden in Reagieren

Hier sehen Sie eine Neufassung Ihres Beispiels mit gängigen React-Mustern. Ich verwende kontrollierte Komponenten für die Formulareingaben. Die Mehrheit der funktionalen Konzepte, über die wir gesprochen haben, leben wirklich unter der Haube in React, also ist dies eine ziemlich einfache Implementierung, die nichts Besonderes verwendet.

%Vor%

Die Verwendung von state scheint wahrscheinlich ein Nebeneffekt zu sein, oder? In gewisser Hinsicht ist es das, aber wenn man in die React-Interna eingräbt, kann dies eine funktionellere Implementierung ergeben, als man aus unserer einzigen Komponente sehen kann.

Hier ist Form für Ihr Beispiel. Beachten Sie, dass wir die Einreichung hier auf verschiedene Arten behandeln können. Eine Möglichkeit besteht darin, die username und password als Requisiten in Form (wahrscheinlich als generische data Requisite) zu übergeben. Eine andere Möglichkeit besteht darin, einen handleSubmit Callback spezifisch für dieses Formular zu übergeben (genau wie für validate ).

%Vor%

Sie könnten auch ein anderes Form schreiben, aber mit anderen Eingaben

%Vor%

Zum Beispiel kann Ihre App beide Form Implementierungen darstellen:

%Vor%

Schließlich verwenden wir ReactDOM anstelle von innerHTML

%Vor%

Die Funktion von React wird oft durch die Verwendung von JSX ausgeblendet. Ich möchte Sie ermutigen, sich darüber zu informieren, dass das, was wir tun, wirklich nur aus einer Reihe von zusammengesetzten Funktionen besteht. Die offiziellen Dokumente decken das ziemlich gut ab.

Zur weiteren Lektüre hat James K. Nelson einige hervorragende Quellen zu React zusammengestellt, die bei Ihrem funktionalen Verständnis helfen sollten: Ссылка

    
Luke M Willis 13.11.2017 21:15
quelle