Renderizzare Liste
Spesso vorrai visualizzare più componenti simili da una collezione di dati. Puoi usare i metodi degli array di JavaScript per manipolare un array di dati. In questa pagina, userai filter()
e map()
con React per filtrare e trasformare il tuo array di dati in un array di componenti.
Imparerai
- Come renderizzare componenti da un array usando
map()
di JavaScript - Come renderizzare solo componenti specifici usando
filter()
di JavaScript - Quando e perché usare le React keys
Renderizzare dati da array
Immagina di avere una lista di contenuti.
<ul>
<li>Creola Katherine Johnson: mathematician</li>
<li>Mario José Molina-Pasquel Henríquez: chemist</li>
<li>Mohammad Abdus Salam: physicist</li>
<li>Percy Lavon Julian: chemist</li>
<li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>
L’unica differenza tra questi elementi della lista è il loro contenuto, i loro dati. Avrai spesso bisogno di mostrare diverse istanze dello stesso componente usando dati diversi quando costruisci interfacce: dalle liste di commenti alle gallerie di immagini del profilo. In queste situazioni, puoi memorizzare quei dati in oggetti e array JavaScript e usare metodi come map()
e filter()
per renderizzare liste di componenti da essi.
Qui un breve esempio di come generare una lista di elementi da un array:
- Sposta i dati in un array:
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist'
];
- Mappa i membri di
people
in un array di nodi JSX,listItems
:
const listItems = people.map(person => <li>{person}</li>);
- Ritorna
listItems
dal tuo componente all’interno di<ul>
:
return <ul>{listItems}</ul>;
Qui puoi vedere il risultato:
const people = [ 'Creola Katherine Johnson: mathematician', 'Mario José Molina-Pasquel Henríquez: chemist', 'Mohammad Abdus Salam: physicist', 'Percy Lavon Julian: chemist', 'Subrahmanyan Chandrasekhar: astrophysicist' ]; export default function List() { const listItems = people.map(person => <li>{person}</li> ); return <ul>{listItems}</ul>; }
Nota che il sandbox sopra visualizza un errore di console:
Imparerai a risolvere questo errore più avanti in questa pagina. Prima di arrivare a quello, aggiungiamo un po’ di struttura ai tuoi dati.
Filtrare array di elementi
Questi dati possono essere strutturati ancora di più.
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'chemist',
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
}];
Diciamo che vuoi ottenere un modo per mostrare solo le persone la cui professione è 'chemist'
. Puoi usare il metodo filter()
di JavaScript per ritornare solo quelle persone. Questo metodo prende un array di elementi, li passa attraverso un “test” (una funzione che ritorna true
o false
), e ritorna un nuovo array solo con gli elementi che hanno passato il test (ritornato true
).
Vuoi solamente gli elementi dove profession
è uguale a'chemist'
. La funzione “test” per questo scopo è (person) => person.profession === 'chemist'
. Ecco come mettere insieme il tutto:
- Crea un nuovo array di sole persone “chemist”,
chemists
, chiamandofilter()
supeople
filtrando perperson.profession === 'chemist'
:
const chemists = people.filter(person =>
person.profession === 'chemist'
);
- Adesso mappa
chemists
:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
- Infine, ritorna
listItems
dal tuo componente:
return <ul>{listItems}</ul>;
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const chemists = people.filter(person => person.profession === 'chemist' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} known for {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
Manetenere liste di elementi in ordine con key
Avrai notato che tutte le sandbox sopra mostrano un errore nella console:
Devi assegnare ad ogni elemento dell’array una key
— una stringa o un numero che lo identifica univocamente tra gli altri elementi di quell’array:
<li key={person.id}>...</li>
Le key dicono a React a quale elemento dell’array corrisponde ogni componente, così che possa associarli in seguito. Questo diventa importante se gli elementi dell’array possono muoversi (ad esempio a causa di un ordinamento), essere inseriti o eliminati. Una key
ben scelta aiuta React a capire cosa è successo esattamente, e a fare gli aggiornamenti corretti all’albero del DOM.
Piuttosto che generare le key al volo, dovresti includerle nei tuoi dati:
export const people = [{ id: 0, // Usato in JSX come key name: 'Creola Katherine Johnson', profession: 'mathematician', accomplishment: 'spaceflight calculations', imageId: 'MK3eW3A' }, { id: 1, // Usato in JSX come key name: 'Mario José Molina-Pasquel Henríquez', profession: 'chemist', accomplishment: 'discovery of Arctic ozone hole', imageId: 'mynHUSa' }, { id: 2, // Usato in JSX come key name: 'Mohammad Abdus Salam', profession: 'physicist', accomplishment: 'electromagnetism theory', imageId: 'bE7W1ji' }, { id: 3, // Usato in JSX come key name: 'Percy Lavon Julian', profession: 'chemist', accomplishment: 'pioneering cortisone drugs, steroids and birth control pills', imageId: 'IOjWm71' }, { id: 4, // Usato in JSX come key name: 'Subrahmanyan Chandrasekhar', profession: 'astrophysicist', accomplishment: 'white dwarf star mass calculations', imageId: 'lrWQx8l' }];
Approfondimento
Cosa farai se ogni elemento della lista deve renderizzare non uno, ma diversi nodi DOM?
La breve sintassi Fragment <>...</>
non ti permette di passare una key
, quindi devi o raggrupparli in un singolo <div>
, o usare la sintassi leggermente più lunga e più esplicita <Fragment>
:
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
I Fragment scompaiono dal DOM, quindi questo produrrà una lista piatta di <h1>
, <p>
, <h1>
, <p>
, e così via.
Da dove prendere la key
Diverse fonti di dati forniscono diverse fonti di key:
- Dati provenienti da un database: Se i tuoi dati provengono da un database, puoi usare le chiavi / ID del database, che sono uniche per natura.
- Dati generati localmente: Se i tuoi dati sono generati e mantenuti localmente (ad esempio note in un’app per prendere appunti), usa un contatore crescente,
crypto.randomUUID()
o un pacchetto comeuuid
quando crei gli elementi.
Regole delle key
- Le key devono essere uniche tra i loro simili. Tuttavia, è possibile utilizzare le stesse key per i nodi JSX in array diversi.
- Le key non devono cambiare o questo ne annulla lo scopo! Non generarle durante il rendering.
Perchè React ha bisogno delle key?
Immagina se i file sul tuo desktop non avessero nomi. Al contrario, ti riferiresti a loro in base al loro ordine: il primo file, il secondo file e così via. Potresti abituarti, ma una volta eliminato un file, sarebbe confuso. Il secondo file diventerebbe il primo file, il terzo file sarebbe il secondo file e così via.
I nomi dei file in una cartella e le key JSX in un array servono a uno scopo simile. Ci consentono di identificare univocamente un elemento tra i suoi simili. Una key ben scelta fornisce più informazioni rispetto alla posizione all’interno dell’array. Anche se la posizione cambia a causa del riordinamento, la key
consente a React di identificare l’elemento per tutta la sua durata.
Riepilogo
In questa pagina hai imparato:
- Come muovere i dati fuori dai componenti e in strutture dati come array e oggetti.
- Come generare una lista componenti simili con
map()
di JavaScript. - Come creare array di elementi filtrati con
filter()
di JavaScript. - Il perchè e il come impostare
key
su ogni componente in una collezione in modo che React possa tener traccia di ognuno di essi anche se la loro posizione o i dati cambiano.
Sfida 1 di 4: Dividere una lista in due
Questo esempio mostra una lista di tutte le persone.
Cambialo in modo da mostrare due liste separate una dopo l’altra: Chemists e Everyone Else.. Come in precedenza, puoi determinare se una persona è un chimico controllando se person.profession === 'chemist'
.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} known for {person.accomplishment} </p> </li> ); return ( <article> <h1>Scientists</h1> <ul>{listItems}</ul> </article> ); }