Wenn Sie bereits ein Profi sind, erinnern Sie sich vielleicht an Ihre Krücken. Oder bieten Sie vielleicht bessere Lösungen für die beschriebenen Probleme.
Dieser Artikel konzentriert sich auf meine persönliche Meinung zur Organisation der Zusammensetzung von Komponenten.
Fangen wir klein an
Betrachten wir eine abstrakte Form. Wir werden bedeuten, dass das Formular viele Felder enthält (ca. 10-15 Teile), aber damit die Augen nicht hochlaufen, nehmen wir ein Formular mit 4 Feldern als Beispiel.
Ein mehrstufiges Objekt des folgenden Typs kommt am Eingang der Komponente an:
const unit = {
name: 'unit1',
color: 'red',
size: {
width: 2,
height: 4,
},
}
Ein unerfahrener Entwickler (wie ich im ersten Monat der Arbeit mit React) erledigt dies alles in einer Komponente, in der die Eingabewerte im folgenden Status gespeichert werden:
const Component = ({ values, onSave, onCancel }) => {
const [ state, setState ] = useState({});
useEffect(() => {
setState(values);
}, [ values, setState ]);
return <div className="form-layout">
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, name: value }))
}/>
</div>
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, color: value }))
}/>
</div>
<div className="size">
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, size: { width: value } }))
}/>
</div>
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, size: { height: value } }))
}/>
</div>
</div>
<div className="buttons">
<Button onClick={() => onSave(state)}>Save</Button>
<Button onClick={() => onCancel()}>Cancel</Button>
</div>
</div>
}
Wenn der Kunde sieht, wie schnell der Entwickler damit fertig geworden ist, bietet er an, ein anderes Formular basierend auf diesem Formular zu erstellen, jedoch ohne den Block "Größe".
Es gibt 2 Optionen (und beide sind nicht korrekt):
- Sie können die erste Komponente kopieren und hinzufügen, was fehlt, oder den Überschuss entfernen. Dies geschieht normalerweise, wenn sie nicht ihre eigene Komponente als Grundlage nehmen und Angst haben, etwas darin zu zerbrechen.
- Fügen Sie den Parametern zusätzliche Komponenteneinstellungen hinzu.
Wenn das Projekt nach der Implementierung von 3-5 Formularen beendet ist, hat der Entwickler Glück.
Aber normalerweise ist dies nur der Anfang und die Anzahl der verschiedenen Formen wächst nur.
Dann ist ein ähnlicher erforderlich, jedoch ohne den Farbblock.
Dann ein ähnlicher, aber mit einem neuen "Beschreibungs" -Block.
Machen Sie dann einige Blöcke nur zum Lesen.
Dann muss eine ähnliche Form in eine andere Form eingefügt werden - im Allgemeinen Traurigkeit, die manchmal daraus resultiert.
Neue Formulare durch Kopieren
Ein Entwickler, der einen Copy-Around-Ansatz verfolgt, kann natürlich schnell neue Formulare implementieren. Es wird zwar weniger als 10 geben. Aber dann wird die Stimmung allmählich sinken.
Besonders wenn eine Neugestaltung stattfindet. Korrigieren Sie die Einrückungen zwischen den Blöcken des Formulars "ein wenig", ändern Sie die Farbauswahlkomponente. Schließlich kann nicht alles auf einmal vorhergesehen werden und viele Designlösungen müssen nach ihrer Implementierung überarbeitet werden.
Es ist wichtig, auf die häufige Erwähnung einer "ähnlichen Form" zu achten. Immerhin ist das Produkt eins und alle Formen sollten ähnlich sein. Infolgedessen müssen Sie sich mit sehr uninteressanten und routinemäßigen Arbeiten befassen, um dasselbe in jedem Formular zu überarbeiten, und übrigens müssen Tester auch jedes Formular überprüfen.
Im Allgemeinen kommt man auf die Idee. Kopieren Sie keine ähnlichen Komponenten.
Neue Formen durch Verallgemeinerung
Wenn der Entwickler den zweiten Weg gewählt hat, ist er natürlich auf einem Pferd - könnte man meinen. Es hat nur wenige Komponenten, mit denen Sie Dutzende von Formen zeichnen können. Korrigieren Sie die Einrückung während des gesamten Projekts oder ändern Sie die „Farb“ -Komponente. Hiermit werden zwei Zeilen im Code korrigiert, und der Tester muss nur an wenigen Stellen eine Überprüfung durchführen.
Tatsächlich führte dieser Weg jedoch zu einer sehr schwer zu pflegenden Komponente.
Es ist schwierig, es zu benutzen, tk. Viele Parameter, einige werden fast gleich genannt, um zu verstehen, wofür jeder Parameter verantwortlich ist, müssen Sie hineingehen.
<Component
isNameVisible={true}
isNameDisabled={true}
nameLabel="Model"
nameType="input"
isColorVisible={true}
isColorDisabled={false}
colorType={'dropdown'}
isSizeVisible={true}
isHeightVisible={true}
isWidthDisabled={false}
/>
Es ist auch schwer zu pflegen. In der Regel gibt es komplexe Verflechtungsbedingungen im Inneren, und das Hinzufügen einer neuen Bedingung kann alles andere zerstören. Das Optimieren der Komponente zur Ausgabe eines Formulars kann den Rest beschädigen.
Im Allgemeinen kommt man auf die Idee. Machen Sie der Komponente nicht viele Eigenschaften.Um die Probleme der zweiten Option zu lösen, starten die Entwickler was? Recht. Als echte Entwickler entwickeln sie etwas, das das Einrichten einer komplexen Komponente erleichtert.
Zum Beispiel machen sie den Parameter fields (also wie Spalten in der Reaktionstabelle). Und die Parameter der Felder werden dort übergeben: Welches Feld ist sichtbar, welches kann nicht bearbeitet werden, der Name des Feldes.
Der Komponentenaufruf wird folgendermaßen:
const FIELDS = {
name: { visible: true, disabled: true, label: 'Model', type: 'input' },
color: { visible: true, disabled: false, type: 'dropdown' },
size: { visible: true },
height: { visible: true },
width: { disabled: false },
}
<Component
values={values}
fields={FIELDS}
/>
Infolgedessen ist der Entwickler stolz auf sich. Er verallgemeinerte die Einstellungen für alle Felder und optimierte den internen Code der Komponente: Jetzt wird für jedes Feld eine Funktion aufgerufen, die die Konfiguration in Requisiten der entsprechenden Komponente umwandelt. Auch nach Typname wird eine andere Komponente gerendert. Ein bisschen mehr und Sie erhalten Ihr eigenes Framework.
Cool? Zu viel.
Hoffentlich wird daraus nicht Folgendes:
const FIELDS = {
name: getInputConfig({ visible: true, disabled: true, label: 'Model'}),
color: getDropDownConfig({ visible: true, disabled: false}),
size: getBlockConfig({ visible: true }),
height: getInputNumberConfig({ visible: true }),
width: getInputNumberConfig({ disabled: false }),
}
<Component
values={values}
fields={FIELDS}
/>
Im Allgemeinen kommt man auf die Idee. Das Rad nicht neu erfinden.
Neue Formen durch Zusammensetzen von Komponenten und verschachtelten Formen
Erinnern wir uns daran, worüber wir noch schreiben. Wir haben bereits eine Reaktionsbibliothek. Es besteht keine Notwendigkeit, neue Designs zu erfinden. Die Komponentenkonfiguration in Reaktion wird mithilfe des JSX-Markups beschrieben
const Form1 = ({ values }) => {
return <FormPanel>
<FormField disabled label=”Model”>
<Input name="name" />
</FormField>
<FormField disabled label=”Color”>
<DropDown name="color" />
</FormField>
<FormPanel>
<FormField disabled label="Height">
<Input name="height" />
</FormField>
<FormField disabled label="Width">
<Input name="width" />
</From Field>
</FormPanelt>
</FormPanel>
}
Anscheinend sind wir wieder bei der ersten Kopieroption. Aber eigentlich nein. Dies ist eine Komposition, die die Probleme der ersten beiden Ansätze beseitigt.
Es gibt eine Reihe von Steinen, aus denen das Formular zusammengesetzt wird. Jeder Stein ist für etwas anderes verantwortlich. Einige für das Layout und das Erscheinungsbild, andere für die Dateneingabe.
Wenn Sie die Einrückungen im gesamten Projekt ändern müssen, reicht es aus, dies in der FormField-Komponente zu tun. Wenn Sie die Arbeit der Dropdown-Liste ändern müssen, erfolgt dies an einer Stelle in der DropDown-Komponente.
Wenn Sie eine ähnliche Form benötigen, aber zum Beispiel, damit kein „Farbfeld“ vorhanden ist, platzieren wir die gemeinsamen Blöcke in separaten Steinen und setzen eine andere Form zusammen.
Wir verschieben den Größenblock in eine separate Komponente:
const Size = () => <FormPanel>
<FormField disabled label="Height">
<Input name="height" />
</FormField>
<FormField disabled label=”Width”>
<Input name="width" />
</From Field>
</FormPanel>
Eine Form mit einer Auswahl an Farben erstellen:
const Form1 = () => <FormPanel>
<FormField disabled label="Color">
<DropDown name="color" />
</FormField>
<FormField disabled label="Model">
<Input name="name" />
</FormField>
<Size name="size" />
</FormPanel>
Wir machen eine ähnliche Form, aber ohne eine Farbe zu wählen:
const Form2 = () => <FormPanel>
<FormField disabled label="Model">
<Input name="name" />
</FormField>
<Size name="size" />
</FormPanel>
Am wichtigsten ist, dass die Person, die einen solchen Code erhält, sich nicht mit den fiktiven Konfigurationen des Vorgängers befassen muss. Alles ist in JSX geschrieben, das jedem Reaktionsentwickler vertraut ist, mit Parameterhinweisen für jede Komponente.
Im Allgemeinen kommt man auf die Idee. Verwenden Sie JSX und Komponentenzusammensetzung.
Ein paar Worte zum Staat
Lassen Sie uns jetzt auf den Staat achten. Genauer gesagt, seine Abwesenheit. Sobald wir einen Status hinzufügen, schließen wir den Datenfluss und es wird schwieriger, die Komponente wiederzuverwenden. Alle Steine müssen zustandslos sein (d. H. Staatenlos). Und nur auf höchster Ebene kann eine aus Ziegeln zusammengesetzte Form mit dem Staat verbunden werden. Wenn das Formular komplex ist, ist es sinnvoll, es in mehrere Container aufzuteilen und jedes Teil mit Redux zu verbinden.
Seien Sie nicht faul, eine separate zustandslose Formularkomponente zu erstellen. Dann haben Sie die Möglichkeit, es als Teil eines anderen Formulars zu verwenden oder ein darauf basierendes Statefull-Formular oder einen Container für die Verbindung mit Redux zu erstellen.
Natürlich kann es in Bausteinen Zustände zum Speichern des internen Zustands geben, der nicht mit dem allgemeinen Datenfluss zusammenhängt. Im internen Status DropDown (Dropdown-Liste) ist es beispielsweise praktisch, das Attribut zu speichern, unabhängig davon, ob es erweitert ist oder nicht.
Im Allgemeinen kommt man auf die Idee. Trennen Sie die Komponenten in Stateless und Statefull.
Gesamt
Es überrascht nicht, dass ich regelmäßig auf alle im Artikel beschriebenen Fehler und die daraus resultierenden Probleme stoße. Ich hoffe, Sie werden sie nicht wiederholen und dann wird die Pflege Ihres Codes viel einfacher.
Ich werde die wichtigsten Punkte wiederholen:
- Kopieren Sie keine ähnlichen Komponenten. Verwenden Sie das DRY-Prinzip.
- Machen Sie keine Komponenten mit vielen Eigenschaften und Funktionen. Jede Komponente sollte für etwas anderes verantwortlich sein (Einzelverantwortung von SOLID)
- Trennen Sie die Komponenten in Stateless und Statefull.
- Erfinde deine Designs nicht neu. Verwenden Sie JSX und Komposition aus Ihren Komponenten.