Il rendering condizionale è una potente funzionalità di React che consente agli sviluppatori di eseguire il rendering dei componenti in base a determinate condizioni.

È un concetto fondamentale che gioca un ruolo importante nella creazione di applicazioni web dinamiche e interattive.

In questa guida completa, analizzeremo in profondità il rendering condizionale in React, trattando le tecniche di base e quelle più avanzate con esempi pratici.

Il rendering condizionale in React

Il rendering condizionale in React consente di controllare dinamicamente i contenuti visualizzati sullo schermo in base a valori specifici che possono essere memorizzati in una variabile, uno stato o un oggetto.

Questo può essere estremamente utile in scenari in cui si desidera mostrare o nascondere determinati elementi dell’interfaccia utente, modificare il layout di una pagina o visualizzare contenuti diversi in base alle interazioni dell’utente.

Il rendering condizionale è importante nelle applicazioni React perché permette di creare interfacce utente dinamiche e interattive in grado di rispondere ai dati e alle interazioni degli utenti in tempo reale.

Contribuisce a migliorare le prestazioni e l’efficienza delle applicazioni evitando il rendering di componenti o elementi non necessari.

Tecniche di base per il rendering condizionale

Ci sono diverse tecniche di base per il rendering condizionale in React. Analizziamole in dettaglio.

Rendering condizionale con l’istruzione if

Uno dei modi più semplici per implementare il rendering condizionale in React è offerto dalla tradizionale istruzione if.

if (condition) {
    return <p>Expression 1</p>;
  } else {
    return <p>Expression 2</p>;
  }

L’istruzione JavaScript if può essere utilizzata all’interno del metodo render() del componente per eseguire il rendering condizionale dei contenuti in base a una determinata condizione.

Ad esempio, si può utilizzare l’istruzione if per visualizzare uno spinner di caricamento in attesa del caricamento dei dati:

import { useState, useEffect } from 'react';
import Spinner from './Spinner';

const MyComponent = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    // Fetch data from an API
    fetch('https://example.com/data')
      .then((response) => response.json())
      .then((data) => {
        setData(data);
        setIsLoading(false);
      });
  }, []);

  if (isLoading) {
    return <Spinner />;
  }

  return <div>{/* Render the data here */}</div>;
};

export default MyComponent;

In questo esempio, MyComponent recupera i dati da un’API utilizzando l’hook useEffect. In attesa del caricamento dei dati, visualizziamo un componente Spinner utilizzando l’istruzione if.

Un altro esempio può essere il rendering di un’interfaccia di fallback quando si verifica un errore durante il rendering del componente:

const MyComponent = ({ data }) => {
  if (!data) {
    return <p>Something went wrong. Please try again later.</p>;
  }

  return <div>{/* Render the data here */}</div>;
};

export default MyComponent;

In questo codice, abbiamo un MyComponent che accetta una proprietà data. Se la proprietà data è errata, renderizziamo un messaggio di errore utilizzando l’istruzione if.

Infine, con l’istruzione if è possibile visualizzare contenuti diversi per diversi ruoli utente:

const MyComponent = ({ user }) => {
  if (user.role === 'admin') {
    return <p>Welcome, admin!</p>;
  } else if (user.role === 'user') {
    return <p>Welcome, user!</p>;
  } else {
    return <p>You are not authorized to access this page.</p>;
  }
};

export default MyComponent;

In questo codice, abbiamo un MyComponent che accetta una proprietà user. A seconda della proprietà user.role, visualizziamo contenuti diversi utilizzando l’istruzione if.

Rendering condizionale con l’operatore ternario

Un altro modo conciso per implementare il rendering condizionale in React è offerto dall’operatore ternario (?) all’interno di JSX.

L’operatore ternario permette di scrivere un’istruzione inline if-else compatta specificando 3 operandi. Il primo operando è la condizione, mentre gli altri due operandi sono le espressioni. Se la condizione è true, verrà eseguita la prima espressione, altrimenti la seconda.

Ad esempio, è possibile eseguire il rendering di diversi componenti in base a una proprietà:

import ComponentA from './ComponentA';
import ComponentB from './ComponentB';

const ExampleComponent = ({ shouldRenderComponentA }) => {
  return (
    <div>
      {shouldRenderComponentA ? <ComponentA /> : <ComponentB />}
    </div>
  );
};

export default ExampleComponent;

In questo codice, abbiamo un ExampleComponent che accetta un oggetto chiamato shouldRenderComponentA. Utilizziamo l’operatore ternario per rendere condizionalmente ComponentA o ComponentB in base al valore della proprietà.

Si può anche rendere un testo diverso in base a uno stato:

import { useState } from 'react';

const ExampleComponent = () => {
  const [showMessage, setShowMessage] = useState(false);

  return (
    <div>
      <button onClick={() => setShowMessage(!showMessage)}>
        {showMessage ? 'Hide message' : 'Show message'}
      </button>
      {showMessage ? <p>Hello, world!</p> : null}
    </div>
  );
};

export default ExampleComponent;

In questo esempio, utilizziamo l’operatore ternario per rendere in modo condizionale un testo diverso a seconda del valore dello stato showMessage. Quando il pulsante viene cliccato, il valore di showMessage viene modificato e il testo viene visualizzato o nascosto di conseguenza.

Infine, è possibile visualizzare uno spinner di caricamento mentre i dati vengono recuperati:

import { useState, useEffect } from 'react';
import Spinner from './Spinner';

const ExampleComponent = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const jsonData = await response.json();
      setData(jsonData);
      setIsLoading(false);
    };
    fetchData();
  }, []);

  return (
    <div>
      {isLoading ? <Spinner /> : <p>{data.title}</p>}
    </div>
  );
};

export default ExampleComponent;

In questo esempio, utilizziamo l’operatore ternario per visualizzare in modo condizionale uno spinner di caricamento mentre i dati vengono prelevati da un’API. Una volta che i dati sono disponibili, rendiamo la proprietà title utilizzando l’operatore ternario.

Rendering condizionale con gli operatori logici AND e OR

Per implementare il rendering condizionale in React è possibile utilizzare anche gli operatori logici AND (&&) e OR (||).

L’operatore logico AND permette di eseguire il rendering di un componente solo se una certa condizione è vera, mentre l’operatore logico OR permette di eseguire il rendering di un componente se una delle due condizioni è vera.

Questi operatori sono utili quando si hanno delle condizioni semplici che stabiliscono se un componente deve essere renderizzato o meno. Ad esempio, se si vuole effettuare il rendering di un pulsante solo se un modulo è valido, si può utilizzare l’operatore logico AND in questo modo:

import { useState } from 'react';

const FormComponent = () => {
  const [formValues, setFormValues] = useState({ username: "", password: "" });

  const isFormValid = formValues.username && formValues.password;

  const handleSubmit = (event) => {
    event.preventDefault();
    // Submit form data
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={formValues.username}
        placeholder="Type Username..."
        onChange={(e) =>
          setFormValues({ ...formValues, username: e.target.value })
        }
      />
      <br />
      <input
        type="password"
        value={formValues.password}
        placeholder="Type Password..."
        onChange={(e) =>
          setFormValues({ ...formValues, password: e.target.value })
        }
      />
      {isFormValid && <button type="submit">Submit</button>}
    </form>
  );
};

export default FormComponent;

In questo esempio, abbiamo un modulo FormComponent con due campi di input per username e password. Stiamo utilizzando l’hook useState per gestire i valori del modulo e la variabile isFormValid per verificare se entrambi i campi di input hanno un valore. Utilizzando l’operatore logico AND (&&), effettuiamo il rendering del pulsante di invio solo se isFormValid è vero. Questo fa sì che il pulsante sia abilitato solo quando il modulo è valido.

Allo stesso modo, potete utilizzare l’operatore OR per visualizzare un messaggio di caricamento se i dati sono ancora in fase di caricamento o un messaggio di errore nel caso in cui si verifichi un errore:

import React, { useEffect, useState } from 'react';

const DataComponent = () => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState('');

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        setData(data);
      } catch (error) {
        setErrorMessage('An error occurred while fetching data.');
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, []);

  return (
    <>
      {errorMessage || isLoading ? (
        <p>{errorMessage || 'Loading...'}</p>
      ) : (
        <ul>
          {data.map((item) => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </>
  );
};

export default DataComponent;

In questo esempio, DataComponent recupera i dati da un’API tramite fetch e li visualizza in un elenco. Utilizziamo l’hook useState per gestire i dati, lo stato di caricamento e il messaggio di errore. Utilizzando l’operatore logico OR (||), possiamo visualizzare un messaggio di caricamento o un messaggio di errore se una delle due condizioni è vera. In questo modo l’utente vede un messaggio che indica lo stato attuale del processo di acquisizione dei dati.

L’utilizzo degli operatori logici AND e OR per il rendering condizionale in React è una soluzione concisa e leggibile per gestire condizioni semplici. Tuttavia, nel caso di una logica più complessa, è meglio seguire altri approcci come le istruzioni di switch.

Tecniche avanzate per il rendering condizionale

A seconda dei requisiti dell’applicazione, il rendering condizionale in React può essere più o meno complesso. Ecco alcune tecniche avanzate che si possono utilizzare per il rendering condizionale in situazioni di maggiore complessità.

Rendering condizionale con le dichiarazioni switch

Sebbene le istruzioni if e gli operatori ternari siano utilizzati spesso per il rendering condizionale, a volte un’istruzione switch può essere più appropriata, soprattutto quando bisogna testare condizioni multiple.

Ecco un esempio:

import React from 'react';
const MyComponent = ({ userType }) => {
  switch (userType) {
    case 'admin':
      return <p>Welcome, admin user!</p>;
    case 'user':
      return <p>Welcome, regular user!</p>;
    default:
      return <p>Please log in to continue.</p>;
  }
};
export default MyComponent;

In questo codice, viene utilizzata un’istruzione switch per eseguire il rendering condizionale dei contenuti in base alla proprietà userType. Questo approccio può essere utile quando si tratta di condizioni multiple e fornisce una soluzione più ordinata e leggibile per gestire una logica complessa.

Rendering condizionale con React Router

React Router è una libreria che permette di gestire il routing lato client nelle applicazioni React e di eseguire il rendering condizionale dei componenti in base al percorso corrente.

Ecco un esempio di rendering condizionale con React Router:

import { useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

import Home from './components/Home';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
import NotFound from './components/NotFound';

const App = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/login">
          <Login setIsLoggedIn={setIsLoggedIn} />
        </Route>
        {isLoggedIn ? (
          <Route path="/dashboard" component={Dashboard} />
        ) : (
          <Route component={NotFound} />
        )}
      </Switch>
    </Router>
  );
};

export default App;

In questo codice, utilizziamo lo stato isLoggedIn per renderizzare in modo condizionale il componente Dashboard se l’utente ha effettuato l’accesso, oppure il componente NotFound se l’utente non ha effettuato l’accesso. Una volta che l’utente ha effettuato l’accesso, il componente Login imposta lo stato isLoggedIn su true.

QUi utilizziamo la proprietà child del componente <Route> per passare il componente Login e la funzione setIsLoggedIn. Questo ci permette di passare le proprietà al componente Login senza specificarli nella proprietà path.

Riepilogo

Il rendering condizionale permette di aggiornare dinamicamente l’interfaccia utente in base a diverse condizioni.

Ci sono approcci diversi a seconda della complessità della logica che genera l’interfaccia dell’applicazione.

Ricordate di mantenere il codice pulito, organizzato e leggibile e di testare sempre attentamente la logica del rendering condizionale per assicurarvi che funzioni sempre come previsto.

State cercando la soluzione di hosting ideale per le vostre applicazioni React? Provate gratuitamente l’Hosting di Applicazioni di Kinsta!

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 200 technical articles majorly around JavaScript and it's frameworks.