Renderizzazione Condizionale

In React, puoi creare componenti distinti che incapsulano il funzionamento di cui hai bisogno. Quindi, puoi renderizzarne solo alcuni, a seconda dello stato della tua applicazione.

La renderizzazione condizionale in React funziona nello stesso modo in cui funzionano le condizioni in JavaScript. Puoi perciò usare operatori come if o l’operatore condizionale per creare elementi che rappresentano lo stato corrente cosicchè React possa aggiornare la UI di conseguenza.

Considera i due componenti:

function BenvenutoUtente(props) {
  return <h1>Bentornato/a!</h1>;
}

function BenvenutoOspite(props) {
  return <h1>Autenticati, per favore</h1>;
}

Creiamo un componente Benvenuto che visualizza l’uno o l’altro dei componenti appena visti a seconda del fatto che l’utente sia autenticato o meno:

function Benvenuto(props) {
  const utenteAutenticato = props.utenteAutenticato;
  if (utenteAutenticato) {
    return <BenvenutoUtente />;
  }
  return <BenvenutoOspite />;
}

ReactDOM.render(
  // Prova a cambiare in utenteAutenticato={true}:
  <Benvenuto utenteAutenticato={false} />,
  document.getElementById('root')
);

Prova su CodePen

Questo esempio renderizza un messaggio di benvenuto diverso a seconda del valore della prop utenteAutenticato.

Variabili Elemento

Le variabili possono contenere elementi. Ciò ti permette di renderizzare condizionatamente parti del componente mentre il resto dell’output non cambia.

Considera questi due nuovi componenti che rappresentano bottoni di Logout e Login:

function BottoneLogin(props) {
  return <button onClick={props.onClick}>Login</button>;
}

function BottoneLogout(props) {
  return <button onClick={props.onClick}>Logout</button>;
}

Nell’esempio di seguito, creeremo un componente stateful chiamato ControlloLogin.

Esso renderizzerà <BottoneLogin /> o <BottoneLogout /> a seconda del suo stato corrente. Renderizzerà inoltre il componente <Benvenuto /> dell’esempio precedente:

class ControlloLogin extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {utenteAutenticato: false};
  }

  handleLoginClick() {
    this.setState({utenteAutenticato: true});
  }

  handleLogoutClick() {
    this.setState({utenteAutenticato: false});
  }

  render() {
    const utenteAutenticato = this.state.utenteAutenticato;
    let bottone;

    if (utenteAutenticato) {
      bottone = (
        <BottoneLogout onClick={this.handleLogoutClick} />
      );
    } else {
      bottone = (
        <BottoneLogin onClick={this.handleLoginClick} />
      );
    }

    return (
      <div>
        <Benvenuto utenteAutenticato={utenteAutenticato} />
        {bottone}
      </div>
    );
  }
}

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

Prova su CodePen

Anche se dichiarare una variabile ed usare una condizione con if è un buon modo per renderizzare condizionatamente un componente, a volte è preferibile usare una sintassi più corta. Esistono diversi modi per definire condizioni inline (ossia nella stessa riga), diamo uno sguardo.

Condizione If Inline con Operatore Logico &&

Puoi incorporare espressioni in JSX racchiudendole in parentesi graffe. Lo stesso vale per l’operatore logico JavaScript && che può tornare utile quando vogliamo includere un elemento condizionatamente:

function CasellaDiPosta(props) {
  const messaggiNonLetti = props.messaggiNonLetti;
  return (
    <div>
      <h1>Ciao!</h1>
      {messaggiNonLetti.length > 0 && (
        <h2>
          Hai {messaggiNonLetti.length} messaggi non letti.
        </h2>
      )}
    </div>
  );
}

const messaggi = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <CasellaDiPosta messaggiNonLetti={messaggi} />,
  document.getElementById('root')
);

Prova su CodePen

Funziona perché in JavaScript, true && espressione si risolve sempre in espressione, mentre false && espressione si risolve sempre in false.

Per questo, se la condizione è true, l’elemento dopo && verrà renderizzato. Se invece è false, React lo ignorerà.

Condizioni If-Else Inline con Operatore Condizionale

Un altro metodo per renderizzare condizionatamente elementi inline è quello di usare l’operatore condizionale JavaScript condizione ? true : false.

Nell’esempio di seguito, lo useremo per renderizzare condizionatamente un breve blocco di testo.

render() {
  const utenteAutenticato = this.state.utenteAutenticato;
  return (
    <div>
      L'utente è <b>{utenteAutenticato ? 'attualmente' : 'non'}</b> autenticato.
    </div>
  );
}

Può essere usato anche per espressioni più lunghe anche se diventa meno ovvio capire cosa sta succedendo:

render() {
  const utenteAutenticato = this.state.utenteAutenticato;
  return (
    <div>
      {utenteAutenticato ? (
        <BottoneLogout onClick={this.handleLogoutClick} />
      ) : (
        <BottoneLogin onClick={this.handleLoginClick} />
      )}
    </div>
  );
}

Proprio come in JavaScript, sta a te scegliere lo stile più appropriato a seconda di cosa tu ed il tuo team ritenete più leggibile. Inoltre, ricorda che se le condizioni diventano troppo complesse, potrebbe essere un segnale del fatto che probabilmente è bene estrarre un componente.

Prevenire la Renderizzazione di un Componente

In alcuni rari casi potresti volere che un componente sia nascosto anche se viene renderizzato da un altro componente. Per ottenere questo risultato devi ritornare null al posto del suo output di renderizzazione.

Nell’esempio di seguito, il componente <MessaggioAvviso /> viene renderizzato a seconda del valore della prop chiamata attenzione. Se il valore della prop è false, il componente non viene renderizzato:

function MessaggioAvviso(props) {
  if (!props.attenzione) {
    return null;
  }

  return <div className="warning">Attenzione!</div>;
}

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

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

  render() {
    return (
      <div>
        <MessaggioAvviso
          attenzione={this.state.mostraAvviso}
        />
        <button onClick={this.handleToggleClick}>
          {this.state.mostraAvviso ? 'Nascondi' : 'Mostra'}
        </button>
      </div>
    );
  }
}

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

Prova su CodePen

Ritornando null dal metodo render di un componente, non modifica il comportamnento dei metodi di lifecycle del componente. Ad esempio componentDidUpdate viene ancora chiamato.