Es gibt bereits einige großartige Antworten, aber ich denke nicht, dass sie sehr gut erklärt wurden, und einige der angegebenen Methoden enthalten einige Fallstricke, die die Leute stören könnten. Ich werde also die drei Hauptwege (plus eine Option außerhalb des Themas) durchgehen, um dies zu tun und die Vor- und Nachteile zu erklären. Ich schreibe dies hauptsächlich, weil Option 1 sehr empfohlen wurde und es viele potenzielle Probleme mit dieser Option gibt, wenn sie nicht richtig verwendet wird.
Option 1: Bedingtes Rendern im übergeordneten Element.
Diese Methode gefällt mir nur, wenn Sie die Komponente nur einmal rendern und dort belassen. Das Problem ist, dass jedes Mal, wenn Sie die Sichtbarkeit umschalten, die Komponente von Grund auf neu erstellt wird. Hier ist das Beispiel. LogoutButton oder LoginButton werden im übergeordneten LoginControl bedingt gerendert. Wenn Sie dies ausführen, werden Sie feststellen, dass der Konstruktor bei jedem Klick auf die Schaltfläche aufgerufen wird. https://codepen.io/Kelnor/pen/LzPdpN?editors=1111
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
class LogoutButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created logout button');
}
render(){
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
class LoginButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created login button');
}
render(){
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
Jetzt ist React ziemlich schnell darin, Komponenten von Grund auf neu zu erstellen. Es muss jedoch immer noch Ihren Code aufrufen, wenn Sie ihn erstellen. Wenn Ihr Konstruktor-, componentDidMount-, Rendering- usw. Code also teuer ist, wird die Anzeige der Komponente erheblich verlangsamt. Dies bedeutet auch, dass Sie dies nicht für statusbehaftete Komponenten verwenden können, bei denen der Status beim Ausblenden beibehalten (und beim Anzeigen wiederhergestellt) werden soll. Der einzige Vorteil besteht darin, dass die ausgeblendete Komponente erst erstellt wird, wenn sie ausgewählt ist. Versteckte Komponenten verzögern also nicht das anfängliche Laden der Seite. Es kann auch Fälle geben, in denen Sie möchten, dass eine Stateful-Komponente beim Umschalten zurückgesetzt wird. In diesem Fall ist dies die beste Option.
Option 2: Bedingtes Rendern im Kind
Dadurch werden beide Komponenten einmal erstellt. Schließen Sie dann den Rest des Rendercodes kurz, wenn die Komponente ausgeblendet ist. Sie können auch andere Logik in anderen Methoden mit der sichtbaren Stütze kurzschließen. Beachten Sie das console.log auf der Codepen-Seite. https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
<LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
<LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
</div>
);
}
}
class LogoutButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created logout button');
}
render(){
if(!this.props.isLoggedIn){
return null;
}
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
class LoginButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created login button');
}
render(){
if(this.props.isLoggedIn){
return null;
}
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
Wenn die Initialisierungslogik schnell ist und die untergeordneten Elemente zustandslos sind, werden Sie keinen Unterschied in der Leistung oder Funktionalität feststellen. Warum sollte React jedoch bei jedem Umschalten eine brandneue Komponente erstellen? Wenn die Initialisierung jedoch teuer ist, wird sie bei Option 1 jedes Mal ausgeführt, wenn Sie eine Komponente umschalten, die die Seite beim Wechseln verlangsamt. Option 2 führt alle Inits der Komponente beim Laden der ersten Seite aus. Die erste Ladung verlangsamen. Sollte nochmal notieren. Wenn Sie die Komponente nur einmal basierend auf einer Bedingung anzeigen und nicht umschalten oder möchten, dass sie beim Umschalten zurückgesetzt wird, ist Option 1 in Ordnung und wahrscheinlich die beste Option.
Wenn das langsame Laden von Seiten jedoch ein Problem darstellt, bedeutet dies, dass Sie in einer Lebenszyklusmethode teuren Code haben, und das ist im Allgemeinen keine gute Idee. Sie können und sollten wahrscheinlich das langsame Laden von Seiten lösen, indem Sie den teuren Code aus den Lebenszyklusmethoden entfernen. Verschieben Sie es in eine asynchrone Funktion, die von ComponentDidMount gestartet wurde, und lassen Sie den Rückruf es mit setState () in eine Statusvariable setzen. Wenn die Statusvariable null ist und die Komponente sichtbar ist, muss die Renderfunktion einen Platzhalter zurückgeben. Andernfalls rendern Sie die Daten. Auf diese Weise wird die Seite schnell geladen und die Registerkarten werden beim Laden gefüllt. Sie können die Logik auch in das übergeordnete Element verschieben und die Ergebnisse als Requisiten an die untergeordneten Elemente senden. Auf diese Weise können Sie priorisieren, welche Registerkarten zuerst geladen werden. Oder speichern Sie die Ergebnisse im Cache und führen Sie die Logik nur aus, wenn eine Komponente zum ersten Mal angezeigt wird.
Option 3: Klassenverstecken
Das Verstecken von Klassen ist wahrscheinlich am einfachsten zu implementieren. Wie bereits erwähnt, erstellen Sie einfach eine CSS-Klasse mit display: none und weisen die Klasse basierend auf prop zu. Der Nachteil ist, dass der gesamte Code jeder versteckten Komponente aufgerufen wird und alle versteckten Komponenten an das DOM angehängt werden. (Option 1 erstellt die ausgeblendeten Komponenten überhaupt nicht. Und Option 2 schließt unnötigen Code kurz, wenn die Komponente ausgeblendet ist, und entfernt die Komponente vollständig aus dem DOM.) Es scheint, dass dies beim Umschalten der Sichtbarkeit nach einigen von Kommentatoren durchgeführten Tests schneller ist andere Antworten, aber ich kann nicht mit ihnen sprechen.
Option 4: Eine Komponente, aber Requisiten ändern. Oder vielleicht überhaupt keine Komponente und HTML zwischenspeichern.
Dieser funktioniert nicht für jede Anwendung und ist kein Thema, da es nicht darum geht, Komponenten auszublenden, aber für einige Anwendungsfälle ist er möglicherweise eine bessere Lösung als das Ausblenden. Angenommen, Sie haben Registerkarten. Möglicherweise können Sie eine Reaktionskomponente schreiben und mit den Requisiten ändern, was auf der Registerkarte angezeigt wird. Sie können JSX auch in Statusvariablen speichern und mithilfe einer Requisite entscheiden, welche JSX in der Renderfunktion zurückgegeben werden soll. Wenn die JSX generiert werden muss, tun Sie dies und zwischenspeichern Sie sie im übergeordneten Element und senden Sie die richtige als Requisite. Oder generieren Sie im Kind und zwischenspeichern Sie es im Zustand des Kindes und verwenden Sie Requisiten, um das aktive auszuwählen.