Bedingte Darstellung

Mit React können verschiedene Komponenten erstellt werden, die ein gewünschtes Verhalten kapseln. In Abhängigkeit vom State der Anwendung können dann einige davon dargestellt werden.

Die bedingte Darstellung (engl. conditional rendering) in React funktioniert genauso wie Bedingungen in JavaScript. Benutze JavaScript Operatoren wie if oder den Bedingten Operator um Elemente zu erstellen, welche den aktuellen State widerspiegeln. React aktualisiert dementsprechend die aktuelle Benutzeroberfläche.

Stelle dir diese beiden Komponenten vor:

function UserGreeting(props) {
  return <h1>Willkommen zurück!</h1>;
}

function GuestGreeting(props) {
  return <h1>Bitte melde dich an.</h1>;
}

Wir erstellen eine Greeting Komponente, die eine dieser Komponenten anzeigt, je nachdem ob der Benutzer angemeldet ist oder nicht.

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  // Probiere mal isLoggedIn={true} aus:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

Auf CodePen ausprobieren

Abhängig vom Wert des isLoggedIn Prop stellt das Beispiel eine der Begrüßungen dar.

Element Variablen

Man kann Elemente auch in Variablen speichern. Das kann hilfreich sein, wenn man einen Teil der Komponente bedingt darstellen und den Rest unverändert lassen möchte.

Betrachten wir diese beiden neuen Komponenten, welche Anmelde- und Abmeldebuttons darstellen:

function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Anmelden
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Abmelden
    </button>
  );
}

Im unteren Beispiel erstellen wir eine zustandsbehaftete Komponente, die wir LoginControl nennen.

Sie wird je nach aktuellem State entweder einen <LoginButton /> oder einen <LogoutButton /> darstellen. Außerdem wird sie immer das <Greeting /> aus dem vorherigen Beispiel anzeigen.

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;

    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Auf CodePen ausprobieren

Während Variablen und if Ausdrücke einen guten Weg darstellen um eine Komponente bedingt anzuzeigen, benötigt man manchmal eine etwas kürzere Schreibweise. Es gibt mehrere Wege, Bedingungen direkt in JSX mit aufzunehmen. Diese werden anschließend erklärt.

Bedingung in JSX mit dem logischen && Operator

Es können beliebige Ausdrücke in JSX verwendet werden, indem man sie in geschweifte Klammern schreibt. Das beinhaltet auch den logischen && Operator aus JavaScript. Dieser kann beim bedingten Darstellen eines Elements sehr nützlich sein.

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hallo!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          Du hast {unreadMessages.length} ungelesene Nachrichten.
        </h2>
      }
    </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages={messages} />,
  document.getElementById('root')
);

Auf CodePen ausprobieren

Das funktioniert, weil true && ausdruck in JavaScript immer zu ausdruck evaluiert und false && ausdruck immer zu false evaluiert.

Wenn die Bedingung also true ergibt, wird das Element rechts neben dem && angezeigt. Wenn sie hingegen false ergibt wird sie von React ignoriert und übersprungen.

In JSX eingebettetes If-Else mit dem bedingten Operator

Eine andere Methode wie man Elemente bedingt in JSX eingebettet darstellen kann, ist die Nutzung des bedingten Operators bedingung ? true : false aus JavaScript.

Im folgenden Beispiel wird er genutzt um einen kurzen Text bedingt darzustellen.

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      Der Benutzer ist <b>{isLoggedIn ? 'zur Zeit' : 'nicht'}</b> eingeloggt.
    </div>
  );
}

Der Operator kann auch für größere Ausdrücke genutzt werden, wobei es dann schwerer nachzuvollziehen ist was passiert:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}

Wie in JavaScript auch, ist es dir überlassen welche Methode du für passend hälst und was du und dein Team lesbarer findet. Bedenke: Wenn Bedingungen zu komplex werden, könnte ein guter Zeitpunkt sein um sie in eine eigene Komponente auszulagern.

Darstellung einer Komponente unterbinden

In seltenen Fällen möchtest du womöglich eine Komponente ausblenden, obwohl sie von einer anderen Komponente dargestellt wird. Dafür kannst du null anstelle des Inhalts als Ausgabewert zurückgeben.

Im folgenden Beispiel, wird der <WarningBanner /> in Abhängigkeit vom Wert warn aus den Props dargestellt. Wenn der Wert des Props false ist, wird die Komponente nicht dargestellt:

function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    <div className="warning">
      Warnung!
    </div>
  );
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {showWarning: true};
    this.handleToggleClick = this.handleToggleClick.bind(this);
  }

  handleToggleClick() {
    this.setState(state => ({
      showWarning: !state.showWarning
    }));
  }

  render() {
    return (
      <div>
        <WarningBanner warn={this.state.showWarning} />
        <button onClick={this.handleToggleClick}>
          {this.state.showWarning ? 'Ausblenden' : 'Anzeigen'}
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Page />,
  document.getElementById('root')
);

Auf CodePen ausprobieren

Der Rückgabewert null aus der render Methode einer Komponente hat keinen Einfluss auf die Aufrufe der Lifecycle-Methoden. componentDidUpdate wird beispielsweise weiterhin aufgerufen.