Aggiungere le Interazioni

Alcune cose sullo schermo si aggiornano in risposta all’input dell’utente. Ad esempio, cliccare su una galleria d’immagini modifica l’immagine corrente. In React, i dati che cambiano nel tempo vengono chiamati state. Puoi aggiungere lo state a qualsiasi componente e aggiornarlo secondo necessità. In questo capitolo, imparerai a scrivere componenti che gestiscono interazioni, aggiornano il loro state, e visualizzano diversi output nel tempo.

Rispondere agli eventi

React ti consente di aggiungere degli event handler al tuo JSX. Gli event handler sono le tue funzioni personalizzate che vengono chiamate in risposta alle interazioni dell’utente, come il click, il passaggio del mouse, la messa a fuoco degli input del form e così via.

Componenti integrati come <button> supportano solo eventi integrati del browser come onClick. Tuttavia, è possibile anche creare i propri componenti e dare ai loro event handler dei nomi specifici, contestualizzati all’applicazione.

export default function App() {
  return (
    <Toolbar
      onPlayMovie={() => alert('Playing!')}
      onUploadImage={() => alert('Uploading!')}
    />
  );
}

function Toolbar({ onPlayMovie, onUploadImage }) {
  return (
    <div>
      <Button onClick={onPlayMovie}>
        Play Movie
      </Button>
      <Button onClick={onUploadImage}>
        Upload Image
      </Button>
    </div>
  );
}

function Button({ onClick, children }) {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
}

Ready to learn this topic?

Leggi Rispondere agli Eventi per imparare ad aggiungere gli event handler.

Read More

State: La memoria di un componente

Spesso i componenti devono cambiare ciò che c’è sullo schermo in seguito a un’interazione. Scrivere nel form deve aggiornare l’input, cliccare “avanti” su un carosello deve cambiare l’immagine mostrata, cliccare “acquista” inserisce un prodotto nel carrello. I componenti devono “ricordare” le cose: l’attuale valore dell’input, l’attuale immagine, il carrello. In React, questo specifico tipo di memoria è detto state.

Puoi aggiungere lo state a un componente con un hook useState. Gli Hook sono speciali funzioni che consentono ai componenti di usare le funzionalità di React (lo state è una di queste). L’hook useState consente di dichiarare una variabile state. Prende lo state iniziale e restituisce una coppia di valori: lo state attuale e una funzione state setter che ti consente di aggiornarlo.

const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);

Ecco come una galleria di immagini usa e aggiorna lo state al click:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);
  const hasNext = index < sculptureList.length - 1;

  function handleNextClick() {
    if (hasNext) {
      setIndex(index + 1);
    } else {
      setIndex(0);
    }
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i>
        by {sculpture.artist}
      </h2>
      <h3>
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? 'Hide' : 'Show'} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img
        src={sculpture.url}
        alt={sculpture.alt}
      />
    </>
  );
}

Ready to learn this topic?

Leggi State: La Memoria di un Componente per imparare a memorizzare un valore e aggiornarlo in base alle interazioni.

Read More

Renderizzazione e commit

Prima che i tuoi componenti siano visualizzati sullo schermo, devono essere renderizzati da React. Comprendere le fasi di questo processo ti aiuterà a riflettere su come viene eseguito il tuo codice e a spiegarne il comportamento.

Immagina che i tuoi componenti siano cuochi in cucina, che assemblano deliziosi piatti. In questo scenario, React è il cameriere che prende le comande dai clienti e porta loro gli ordini. Questo processo di richiesta e servizio della UI ha tre fasi:

  1. Triggerare un render (portare la comanda in cucina)
  2. Renderizzare il componente (preparare l’ordine in cucina)
  3. Committare i cambiamenti al DOM (portare l’ordine al tavolo)
  1. React come cameriere in un ristorante, che prende le comande dagli utenti e li porta alla cucina dei componenti.
    Trigger
  2. Il cuoco Card consegna a React un nuovo componente Card.
    Renderizzazione
  3. React porta la Card al tavolo dell'utente.
    Commit

Illustrato da Rachel Lee Nabors

Ready to learn this topic?

Leggi Renderizzazione e Commit per imparare il ciclo di vita di un aggiornamento UI.

Read More

Lo State come istantanea

A differenza delle normali variabili JavaScript, lo state di React si comporta più come un’istantanea. Impostarlo non modifica la variabile state che già possiedi, ma triggera un re-render. Questo può sorprendere all’inizio!

console.log(count); // 0
setCount(count + 1); // Richiedi un re-render con 1
console.log(count); // Ancora 0!

Questo comportamento aiuta a evitare bug difficili da individuare. Ecco una piccola app di messaggistica. Prova a indovinare cosa succede se premi “Send” e poi selezioni il destinatario Bob. Quale nome apparirà nell’alert cinque secondi dopo?

import { useState } from 'react';

export default function Form() {
  const [to, setTo] = useState('Alice');
  const [message, setMessage] = useState('Hello');

  function handleSubmit(e) {
    e.preventDefault();
    setTimeout(() => {
      alert(`You said ${message} to ${to}`);
    }, 5000);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        To:{' '}
        <select
          value={to}
          onChange={e => setTo(e.target.value)}>
          <option value="Alice">Alice</option>
          <option value="Bob">Bob</option>
        </select>
      </label>
      <textarea
        placeholder="Message"
        value={message}
        onChange={e => setMessage(e.target.value)}
      />
      <button type="submit">Send</button>
    </form>
  );
}

Ready to learn this topic?

Leggi Lo State come Istantanea per imparare perché lo state appare “fisso” e inalterabile dentro gli event handler.

Read More

Accodare più aggiornamenti dello state

Questo componente è difettoso: cliccare “+3” incrementa lo score soltanto una volta.

import { useState } from 'react';

export default function Counter() {
  const [score, setScore] = useState(0);

  function increment() {
    setScore(score + 1);
  }

  return (
    <>
      <button onClick={() => increment()}>+1</button>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
      <h1>Score: {score}</h1>
    </>
  )
}

Lo State come Istantanea spiega a cosa è dovuto questo. Impostare lo state richiede un nuovo re-render, ma non lo modifica nel codice già eseguito. Quindi score continua a essere 0 subito dopo aver chiamato setScore(score + 1).

console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0

Puoi risolvere questo problema passando una funzione updater quando imposti lo state. Nota come sostituire setScore(score + 1) con setScore(s => s + 1) aggiusta il pulsante “+3”. Questo consente di accodare più aggiornamenti dello state.

import { useState } from 'react';

export default function Counter() {
  const [score, setScore] = useState(0);

  function increment() {
    setScore(s => s + 1);
  }

  return (
    <>
      <button onClick={() => increment()}>+1</button>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
      <h1>Score: {score}</h1>
    </>
  )
}

Ready to learn this topic?

Leggi Accodare più Aggiornamenti dello State per imparare ad accodare una sequenza di aggiornamenti dello state.

Read More

Aggiornare gli oggetti nello state

Lo State può contenere qualsiasi tipo di valore JavaScript, inclusi gli oggetti. Tuttavia, non dovresti modificare direttamente gli oggetti e gli array contenuti nello State. Quando vuoi aggiornare un oggetto o un array, dovresti invece crearne uno nuovo (o copiare quello esistente) e, infine, impostare la copia nello state.

Solitamente, userai la sintassi di spread ... per copiare gli oggetti e gli array che desideri modificare. Ad esempio, l’aggiornamento di un oggetto nidificato potrebbe apparire così:

import { useState } from 'react';

export default function Form() {
  const [person, setPerson] = useState({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    setPerson({
      ...person,
      name: e.target.value
    });
  }

  function handleTitleChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        title: e.target.value
      }
    });
  }

  function handleCityChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        city: e.target.value
      }
    });
  }

  function handleImageChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        image: e.target.value
      }
    });
  }

  return (
    <>
      <label>
        Name:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Title:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        City:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Image:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        {' by '}
        {person.name}
        <br />
        (located in {person.artwork.city})
      </p>
      <img
        src={person.artwork.image}
        alt={person.artwork.title}
      />
    </>
  );
}

Se copiare gli oggetti diventa tedioso, puoi usare una libreria come Immer per ridurre il codice ripetitivo:

{
  "dependencies": {
    "immer": "1.7.3",
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "use-immer": "0.5.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {}
}

Ready to learn this topic?

Leggi Aggiornare gli Oggetti nello State per imparare ad aggiornare gli oggetti correttamente.

Read More

Aggiornare gli array nello state

Gli array sono un altro tipo di oggetti JavaScript mutabili che puoi memorizzare nello state e che dovresti trattare come read-only. Come per gli oggetti, quando vuoi aggiornare un array contenuto nello state, devi crearne uno nuovo (o copiare l’esistente), e infine impostare il nuovo array nello state.

import { useState } from 'react';

const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [list, setList] = useState(
    initialList
  );

  function handleToggle(artworkId, nextSeen) {
    setList(list.map(artwork => {
      if (artwork.id === artworkId) {
        return { ...artwork, seen: nextSeen };
      } else {
        return artwork;
      }
    }));
  }

  return (
    <>
      <h1>Art Bucket List</h1>
      <h2>My list of art to see:</h2>
      <ItemList
        artworks={list}
        onToggle={handleToggle} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

Se copiare gli array diventa tedioso, puoi usare una libreria come Immer per ridurre il codice ripetitivo:

{
  "dependencies": {
    "immer": "1.7.3",
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "use-immer": "0.5.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {}
}

Ready to learn this topic?

Leggi Aggiornare gli Array nello State per imparare ad aggiornare gli array correttamente.

Read More

Qual è il prossimo passo?

Dirigiti su Rispondere agli Eventi per iniziare a leggere questo capitolo pagina per pagina!

Oppure, se hai già familiarità con questi argomenti, perché non leggere Gestire lo State?