Compound Components in React ermöglichen es Ihnen, Komponenten mit einer Art verbundenem Zustand zu erstellen, der untereinander verwaltet wird. Ein gutes Beispiel ist die Form-Komponente in Semantic UI React.
Um zu sehen, wie wir Compound Components in einer realen React-Anwendung implementieren können, werden wir ein Compound-Formular (mehrteilig) für Login und Registrierung erstellen. Der Zustand wird in der Formular-Komponente gespeichert und wir werden die Context AP von React verwenden, um diesen Zustand und die Methode vom Context Provider an die Komponente weiterzugeben, die sie benötigt. Die Komponente, die sie benötigt? Sie wird zu einem Abonnenten von Context Consumers.
Das bauen wir
Siehe den Pen React Compound Component von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.
Hier ist ein grober Überblick, der zeigt, wie die folgenden Schritte zusammenpassen

Bevor wir weitergehen, sollten Sie sich mit der React Context API vertraut machen, falls Sie dies noch nicht getan haben. Neal Fennimore demonstriert das Konzept in diesem Beitrag und mein Leitfaden dazu ist ebenfalls einen Blick wert.
Schritt 1: Kontext erstellen
Zuerst initialisieren wir einen neuen Kontext mit der React Context API.
const FormContext = React.createContext({});
const FormProvider = FormContext.Provider;
const FormConsumer = FormContext.Consumer;
Der Provider, FormProvider, wird den Anwendungszustand halten und ihn für Komponenten verfügbar machen, die FormConsumer abonnieren.
Schritt 2: Provider implementieren
Ein Panel enthält das Formular zum Einloggen und das andere das Formular zur Registrierung. Im Provider möchten wir den Zustand deklarieren, der das aktive Panel bestimmt, d.h. das aktuell angezeigte Formular. Wir erstellen auch eine Methode, um von einem Panel zum anderen zu wechseln, wenn eine Überschrift angeklickt wird.
class Form extends React.Component {
state = {
activePanel: "login"
};
render() {
return (
<React.Fragment>
<FormProvider
value={{
activePanel: this.state.activePanel,
actions: {
handlePanelSwitch: newPanel => {
this.setState({
activePanel: newPanel
});
}
}
}}
>
{this.props.children}
</FormProvider>
</React.Fragment>
);
}
}
Standardmäßig wird dem Benutzer das Login-Panel angezeigt. Wenn auf das Registrierungs-Panel geklickt wird, möchten wir es zum aktiven Panel machen, indem wir den Zustand von activePanel mit der Methode handlePanelSwitch() auf signup setzen.
Schritt 3: Consumers implementieren
Wir verwenden FormConsumer, um den Kontext für die Komponenten verfügbar zu machen, die ihn abonnieren. Das bedeutet, die Komponente FormPanel, die für die Anzeige von Panels zuständig ist, sieht wie folgt aus
const FormPanel = props => {
return (
<FormConsumer>
{({ activePanel }) =>
activePanel === props.isActive ? props.children : null
}
</FormConsumer>
);
};
Und die Komponente Panel sieht wie folgt aus
const Panel = props => (
<FormConsumer>
{({ actions }) => {
return (
<div onClick={() => actions.switchPanel(props.id)}>
{props.children}
</div>
);
}}
</FormConsumer>
);
Um zu verstehen, was passiert, betrachten wir den Ansatz hier. Die Login- und Registrierungs-Panels haben eindeutige IDs, die über Props an die Panel-Komponente übergeben werden. Wenn ein Panel ausgewählt wird, erhalten wir die ID und verwenden sie, um activePanel zu setzen und die Formulare zu wechseln. Die FormPanel-Komponente erhält auch den Namen des Panels über die isActive-Prop, und wir prüfen dann, ob der zurückgegebene Wert true ist. Wenn ja, wird das Panel gerendert!
Um den vollständigen Kontext zu erhalten, sieht die Komponente App wie folgt aus
const App = () => {
return (
<div className="form-wrap">
<Form>
<div className="tabs">
<Panel id="login">
<h2 className="login-tab">Login</h2>
</Panel>
<Panel id="signup">
<h2 className="signup-tab">Sign Up</h2>
</Panel>
</div>
<FormPanel isActive="login">
<Login />
</FormPanel>
<FormPanel isActive="signup">
<SignUp />
</FormPanel>
</Form>
</div>
);
};
Sie sehen, wie die Komponenten zusammengesetzt werden, wenn activePanel mit isActive übereinstimmt (was true zurückgeben soll). Die Komponente wird unter diesen Bedingungen gerendert.
Damit ist die Komponente Login wie folgt aufgebaut
const Login = () => {
return (
<React.Fragment>
<div id="login-tab-content">
<form className="login-form" action="" method="post">
<input
type="text"
className="input"
id="user_login"
placeholder="Email or Username"
/>
<input
type="password"
className="input"
id="user_pass"
placeholder="Password"
/>
<input type="checkbox" className="checkbox" id="remember_me" />
<label htmlFor="remember_me">Remember me</label>
<input type="submit" className="button" value="Login" />
</form>
</div>
</React.Fragment>
);
};
Und die Komponente SignUp
const SignUp = () => {
return (
<React.Fragment>
<div id="signup-tab-content" className="active tabs-content">
<form className="signup-form" action="" method="post">
<input
type="email"
className="input"
id="user_email"
placeholder="Email"
/>
<input
type="text"
className="input"
id="user_name"
placeholder="Username"
/>
<input
type="password"
className="input"
id="user_pass"
placeholder="Password"
/>
<input type="submit" className="button" value="Sign Up" />
</form>
</div>
</React.Fragment>
);
};
Verstanden? Gut!
Sie können dieses Muster jederzeit verwenden, wenn Komponenten in Ihrer React-Anwendung impliziten Zustand teilen müssen. Sie können auch Compound Components mit React.cloneElement() erstellen.
Freut mich, dass mein Artikel geholfen hat
Ich habe eine Frage: Was ist der Grund, die letzten beiden Komponenten in React.Fragment einzubinden?
Es hat mich verwirrt, und ich frage mich, ob ich etwas übersehen habe?
Hallo Vladyslav, ich bin mir nicht sicher, auf welchen Teil Sie sich beziehen.