back to top

Componenti React dinamici

Abbiamo ampiamente parlato dellโ€™oggetto props che possiamo usare per passare diverse informazioni ai nostri componenti. In questo articolo introdurremo un secondo concetto fondamentale: lโ€™oggetto state. Finora, infatti, non abbiamo potuto apprezzare in pieno le potenzialitร  di React e ci siamo limitati a vedere componenti configurabili ma statici. A partire da questo articolo, renderemo i nostri componenti dinamici e vedremo come sia possibile eseguire diverse azioni in seguito allโ€™interazione dellโ€™utente con il componente.

Class Component e oggetto State

Ancora una volta, React rende il tutto estremamente semplice. Ricordiamo che lโ€™unica responsabilitร  dellโ€™oggetto props, che รจ un oggetto di sola lettura, รจ quella di passare le informazioni da un componente ai componenti figli. A differenza dellโ€™oggetto props, costituito da valori statici, lโ€™oggetto state rappresenta un insieme di valori che รจ gestito e aggiornato dal componente in cui รจ incapsulato. Se per lโ€™oggetto props, lโ€™unica regola da ricordare era di non modificarne mai il suo valore o quello delle sue proprietร , per lโ€™oggetto state dobbiamo tenere in mente che possiamo modificarlo solo attraverso lโ€™uso della funzione setState(), ereditata da tutti i Class Component. Unโ€™importante differenza, infatti, tra questโ€™ultimi e i Functional Component รจ che solo i primi possono avere uno stato interno. I Functional Component, al contrario, sono stateless perciรฒ non potranno mai avere uno stato interno.

Pubblicitร 
// Non aggiornare mai 'state' direttamente, React non aggiornerร  il componente
this.state.counter = 1 // NO!

// Versione Corretta
this.setState({counter: 1}); // OK

Ogni volta che chiameremo la funzione setState(), React aggiornerร  lโ€™oggetto state con le nuove informazioni. Se poi passeremo le proprietร  dellโ€™oggetto state ai componenti figli tramite props, alla ricezione del nuovo valore, React aggiornerร  anche tali componenti. Approfondiremo lโ€™argomento quando parleremo del ciclo di vita dei Componenti.

Lโ€™oggetto state รจ dunque incapsulato allโ€™interno di un componente che รจ lโ€™unico ad avere il diritto e la responsabilitร  di modificarlo. Ogni componente non saprร  mai se gli altri presentano uno stato interno o meno.

Nellโ€™esempio sottostante vedremo come usare la funzione setState() per aggiornare un componente.

class Dado extends React.Component {
  constructor(props) {
    super(props);
    this.state = {numeroEstratto: 0};
  }
  randomNumber() {
    return Math.round(Math.random() * 5) + 1;
  }
  lanciaDado() {
    this.setState({numeroEstratto: this.randomNumber()});
  }
  render() {
    let valore;
    if (this.state.numeroEstratto === 0) {
      valore = <small>Lancia il dado cliccando <br /> sul pulsante sottostante</small>;
    }else{
      valore = <span>{this.state.numeroEstratto}</span>;
    }
    return (
      <div className="card" >
        <p className="card__number">{valore}</p>
        <button className="card__button" onClick={() => this.lanciaDado()} >Lancia il Dado</button>
      </div>
    )
  }
}

Per prima cosa creiamo un componente Dado. Nel costruttore usiamo il metodo super(props) per invocare il costruttore dellโ€™oggetto padre e inizializzare correttamente il componente. Se non invochiamo il metodo super(props), non possiamo usare la keyword this allโ€™interno del costruttore. Definiamo anche un oggetto state con una sola proprietร  che useremo per tener traccia del numero estratto ad ogni lancio. Nella funzione render() mostriamo un messaggio iniziale se non รจ mai stato premuto il pulsante โ€˜Lancia il dadoโ€™; in caso contrario, verrร  mostrato il numero estratto ad ogni lancio. Ogni volta che viene premuto il pulsante, viene invocata la funzione lanciaDado() che calcola un numero casuale compreso fra 1 e 6 e lo assegna a this.state.numeroEstratto tramite la funzione setState(). Trascuriamo per ora alcuni importanti dettagli in merito allโ€™uso della keyword this allโ€™interno dei componenti. Tratteremo lโ€™argomento in maniera approfondita nei prossimi articoli.

gif animata dell'applicazione React lancio di un dado

Proprietร  della funzione setState()

La funzione setState() presenta alcune caratteristiche che รจ bene tenere in considerazione durante lo sviluppo delle nostre applicazioni.

React potrebbe raggruppare piรน chiamate della funzione setState() ed eseguire lโ€™aggiornamento dellโ€™oggetto state una volta sola. Lโ€™aggiornamento degli oggetti state e props puรฒ avvenire in maniera asincrona e per questo motivo, per calcolare lo stato futuro di un componente, usando i valori attuali dellโ€™oggetto state e props, dovremmo usare unโ€™altra versione di setState() che riceve come unico argomento una funzione. A questa vengono passati due argomenti, ovvero i valori correnti degli oggetti state e props.

/* Facciamo riferimento all'esempio presente nella documentazione ufficiale
*
*  Supponiamo che al momento di invocare this.setState,
*  un componente presenti il seguente stato:
*  
*  this.state = {counter: 1}
*
* Quando verrร  chiamata la funzione setState, prevState.counter
* sarร  uguale a 1 
*/

this.setState((prevState, props) => ({
    counter: prevState.counter + props.increment
}));

Inoltre se un componente presenta un oggetto state con piรน coppie chiave-valore, volendo aggiornare una sola di queste, basterร  passare alla funzione setState() un oggetto con i soli valori che si intendono modificare. React provvederร  a combinare il nuovo oggetto passato con i valori attuali dellโ€™oggetto state

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      proprieta1: "valore1",
      proprieta2: "valore2",
      proprieta3: [1,2,3,4,5]
    }
  }
  // ... resto del componente
}

// ... 
// ...

// Se a un certo punto invochiamo
this.setState({proprieta1: "nuovoValore1"})

// Dopo aver chiamato la funzione setState(), avremo il seguente oggetto state
this.state = {
  proprieta1: "nuovoValore1", // verrร  aggiornata solo proprieta1
  proprieta2: "valore2",
  proprieta3: [1,2,3,4,5]
}

Flusso unidirezionale di dati

Al contrario di altri framework, React introduce il concetto di flusso di dati unidirezionale (Unidirectional Data Flow). Non tutti i componenti sono uguali allโ€™interno della nostra applicazione. Non tutti i componenti dovranno avere uno stato interno, al contrario รจ consigliato costruire componenti senza stato (stateless). Possiamo vedere la nostra applicazione come una gerarchia di componenti. Solitamente avremo qualche componente ai vertici che sarร  responsabile di mantenere lo stato della nostra applicazione e passerร  le informazioni giรน ai componenti figli tramite props. Possiamo immaginare il flusso di informazioni come una cascata.

Definiamo dunque un oggetto, contentente le informazioni dinamiche della nostra applicazione. Non faranno parte di tale oggetto le informazioni dinamiche derivabili o calcolabili a partire da altre. Questo oggetto costituisce lo stato dellโ€™intera applicazione. Fatto ciรฒ, dovremo affidare a un componente il compito di mantenere e modificare tale oggetto. Le informazioni mantenute in esso verranno poi passate ai componenti figli mediante lโ€™uso dellโ€™oggetto props.

Vediamo rapidamente un esempio pratico per capire meglio quanto appena descritto. Supponiamo di avere unโ€™applicazione Rubrica con una serie di contatti. รˆ possibile cercare tra i contatti tramite un campo di ricerca. Ogni volta che digiteremo un carattere nel campo di ricerca, verrร  filtrata la lista dei contatti in base al testo digitato.

Applicazione React Rubrica di Supereroi

Allโ€™interno della nostra applicazione, lโ€™unica informazione dinamica, che cambia in seguito allโ€™interazione dellโ€™utente e non puรฒ essere derivata da niente altro, รจ il testo che digitiamo allโ€™interno del campo di ricerca. La lista dei contatti sarร  invece passata attraverso lโ€™oggetto props alla nostra applicazione. In unโ€™applicazione reale potrebbe capitare di dovere scaricare da un server la lista aggiornata dei contatti, ma anche in questo caso sarร  passata al componente piรน esterno App attraverso lโ€™oggetto props. I due componenti che necessiteranno di usare il testo digitato saranno SearchBar e ContactList. Questโ€™ultimo lo utilizzerร  per filtrare e mostrare una lista aggiornata dei contatti.

Lโ€™oggetto state iniziale della nostra applicazione sarร  quindi {campoDiRicerca: โ€}. Dobbiamo determinare qual รจ il miglior candidato fra i nostri componenti che si occuperร  di mantenere al suo interno tale oggetto. Sarร  questo componente lโ€™unico ad avere la responsabilitร  di aggiornare lโ€™oggetto state attraverso lโ€™invocazione della funzione setState().

I due componenti SearchBar e ContactList hanno bisogno di usare il testo digitato nel campo di ricerca il quale rappresenta lโ€™unica informazione dinamica della nostra applicazione. Entrambi sono racchiusi allโ€™interno del componente App che รจ quindi il candidato ideale per mantenere lโ€™oggetto state. Il componente App invocherร  il metodo setState() per aggiornare il valore di state.campoDiRicerca e passerร  il nuovo valore ai componenti figli attraverso lโ€™oggetto props. Quando questi riceveranno il nuovo valore, verrร  invocata la loro funzione render() che provvederร  al loro aggiornamento.

Schema di funzionamento componenti React

Riprenderemo lโ€™esempio appena discusso nei prossimi articoli. A partire dal prossimo, vedremo come creare strutture piรน complesse e annidare i vari componenti.

Pubblicitร