Passare Props ad un Componente
I componenti React utilizzano le props per comunicare tra loro. Ogni componente genitore può passare alcune informazioni ai suoi componenti figli passandogli le props. Le props potrebbero ricordarti gli attributi HTML, ma attraverso di esse puoi passare qualsiasi valore JavaScript, inclusi oggetti, array e funzioni.
Imparerai
- Come passare props ad un componente
- Come leggere props da un componente
- Come specificare valori di default per le props
- Come passare del JSX ad un componente
- Come cambiano le props nel tempo
Props familiari
Le props sono le informazioni che passi ad un tag JSX. Ad esempio, className
, src
, alt
, width
e height
sono alcune delle props che puoi passare ad un <img>
:
function Avatar() { return ( <img className="avatar" src="https://i.imgur.com/1bX5QH6.jpg" alt="Lin Lanying" width={100} height={100} /> ); } export default function Profile() { return ( <Avatar /> ); }
Le props che puoi passare ad un tag <img>
sono predefinite (ReactDOM si conforma allo standard HTML). Ma puoi passare qualsiasi props ai tuoi componenti, come <Avatar>
, per personalizzarli. Ecco come!
Passare props ad un componente
In questo codice, il componente Profile
non sta passando alcuna props al suo componente figlio, Avatar
:
export default function Profile() {
return (
<Avatar />
);
}
Puoi dare ad Avatar
delle props in due passaggi.
Step 1: Passa le props al componente figlio
Prima di tutto, passa alcune props ad Avatar
. Ad esempio, passiamo due props: person
(un oggetto) e size
(un numero):
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
Adesso puoi leggere queste props all’interno del componente Avatar
.
Step 2: Leggi le props all’interno del componente figlio
Puoi leggere queste props elencando i loro nomi person, size
separati da virgole all’interno di ({
e })
direttamente dopo function Avatar
. Questo ti permette di usarle all’interno del codice di Avatar
, come faresti con una variabile.
function Avatar({ person, size }) {
// person e size sono disponibili qui
}
Aggiungi della logica ad Avatar
che usa le props person
e size
per il rendering, ed è fatta.
Adesso puoi configurare Avatar
per farlo renderizzare in molti modi diversi con props diverse. Prova a modificare i valori!
import { getImageUrl } from './utils.js'; function Avatar({ person, size }) { return ( <img className="avatar" src={getImageUrl(person)} alt={person.name} width={size} height={size} /> ); } export default function Profile() { return ( <div> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> <Avatar size={80} person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }} /> <Avatar size={50} person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} /> </div> ); }
Le props ti fanno pensare ai componenti genitori e figli in maniera indipendente. Ad esempio, puoi cambiare le props person
o size
all’interno di Profile
senza dover pensare a come Avatar
le utilizza. In maniera simile, puoi cambiare come Avatar
usa queste props, senza guardare Profile
.
Puoi pensare alle props come a delle “rotelle” che puoi regolare. Servono allo stesso scopo degli argomenti per le funzioni-infatti, le props sono l’unico argomento per il tuo componente! Le funzioni dei componenti React accettano un singolo argomento, un oggetto props
:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
Solitamente non hai bisogno dell’intero oggetto props
in sé, quindi lo destrutturi in props individuali.
Specificare un valore di default per una prop
Se vuoi dare a una prop un valore di default da utilizzare quando non viene specificato alcun valore, puoi farlo tramite il destructuring mettendo =
ed il valore di default subito dopo il parametro:
function Avatar({ person, size = 100 }) {
// ...
}
Adesso, se <Avatar person={...} />
viene renderizzato senza la prop size
, il size
verrà impostato a 100
.
Il valore di default è utilizzato solo se la prop è mancante o se passi size={undefined}
. Ma se passi size={null}
o size={0}
, il valore di default non verrà utilizzato.
Inoltrare props con la sintassi di spread JSX
Qualche volta, passare le props diventa molto ripetitivo:
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
Non c’è nulla di sbagliato nel codice ripetitivo-può essere più leggibile. Ma a volte puoi preferire la concisione. Alcuni componenti inoltrano tutte le loro props ai loro figli, come fa questo Profile
con Avatar
. Poiché non utilizzano direttamente nessuna delle loro props, può avere senso utilizzare una sintassi più concisa, chiamata “spread”:
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
Questo inoltra tutte le props di Profile
all’Avatar
senza elencare i loro nomi.
Utilizza la sintassi di spread con moderazione. Se la utilizzi in ogni componente, probabilmente c’è qualcosa che non va. Spesso, questo indica che dovresti suddividere i tuoi componenti e passare i figli come JSX. Ne parleremo dopo!
Passare JSX come figlio
È comune annidare tag del browser incorporati:
<div>
<img />
</div>
Qualche volta vorrai annidare i tuoi componenti allo stesso modo:
<Card>
<Avatar />
</Card>
Quando annidi del contenuto all’interno di un tag JSX, il componente genitore riceverà quel contenuto in una prop chiamata children
. Ad esempio, il componente Card
qui sotto riceverà una prop children
impostata ad <Avatar />
e la renderizzerà in un div contenitore:
import Avatar from './Avatar.js'; function Card({ children }) { return ( <div className="card"> {children} </div> ); } export default function Profile() { return ( <Card> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> </Card> ); }
Prova a sostituire l’<Avatar>
all’interno di <Card>
con del testo per vedere come il componente Card
può avvolgere qualsiasi contenuto annidato. Non ha bisogno di “sapere” cosa viene renderizzato al suo interno. Vedrai questo modello flessibile in molti punti.
Puoi pensare a un componente con una prop children
come ad avere un “buco” che può essere “riempito” dai suoi componenti genitori con JSX arbitrario. Spesso utilizzerai la prop children
per i contenitori visivi: pannelli, griglie, ecc.
Illustrato da Rachel Lee Nabors
Come cambiano le props nel tempo
Il componente Clock
qui sotto riceve due props dal suo componente genitore: color
e time
. (Il codice del componente genitore viene omesso perché utilizza state, che al momento non approfondiremo ancora.)
Prova a cambiare il colore nella casella di selezione qui sotto:
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
Questo esempio illustra che un componente può ricevere props diverse nel tempo. Le props non sono sempre statiche! Qui, la prop time
cambia ogni secondo e la prop color
cambia quando selezioni un altro colore. Le props riflettono i dati di un componente in un determinato momento, invece che solo all’inizio.
Tuttavia, le props sono immutabili—un termine della scienza informatica che significa “non modificabile”. Quando un componente ha bisogno di cambiare le sue props (ad esempio, in risposta a un’interazione dell’utente o a nuovi dati), dovrà “chiedere” al suo componente genitore di passargli props diverse—un nuovo oggetto! Le sue vecchie props verranno quindi scartate ed alla fine il motore JavaScript reclamerà la memoria occupata da esse.
Non provare a “cambiare le props”. Quando hai bisogno di rispondere all’input dell’utente (come cambiare il colore selezionato), dovrai “impostare lo state”, che puoi imparare in State: La Memoria di un Componente.
Riepilogo
- Per passare le props, aggiungile al JSX, proprio come faresti con gli attributi HTML.
- Per leggere le props, usa la sintassi di destrutturazione
function Avatar({ person, size })
. - Puoi specificare un valore predefinito come
size = 100
, che viene utilizzato per le props mancanti edundefined
. - Puoi inoltrare tutte le props con la sintassi di spread JSX
<Avatar {...props} />
, ma non abusarne! - Il JSX annidato come
<Card><Avatar /></Card>
apparirà comechildren
della prop del componenteCard
. - Le props sono istantanee di sola lettura nel tempo: ogni render riceve una nuova versione delle props.
- Non puoi cambiare le props. Quando hai bisogno di interattività, dovrai impostare lo state.
Sfida 1 di 3: Estrarre un componente
Questo componente Gallery
contiene alcuni markup molto simili per due profili. Estrai un componente Profile
da esso per ridurre la duplicazione. Dovrai scegliere quali props passargli.
import { getImageUrl } from './utils.js'; export default function Gallery() { return ( <div> <h1>Notable Scientists</h1> <section className="profile"> <h2>Maria Skłodowska-Curie</h2> <img className="avatar" src={getImageUrl('szV5sdG')} alt="Maria Skłodowska-Curie" width={70} height={70} /> <ul> <li> <b>Profession: </b> physicist and chemist </li> <li> <b>Awards: 4 </b> (Nobel Prize in Physics, Nobel Prize in Chemistry, Davy Medal, Matteucci Medal) </li> <li> <b>Discovered: </b> polonium (element) </li> </ul> </section> <section className="profile"> <h2>Katsuko Saruhashi</h2> <img className="avatar" src={getImageUrl('YfeOqp2')} alt="Katsuko Saruhashi" width={70} height={70} /> <ul> <li> <b>Profession: </b> geochemist </li> <li> <b>Awards: 2 </b> (Miyake Prize for geochemistry, Tanaka Prize) </li> <li> <b>Discovered: </b> a method for measuring carbon dioxide in seawater </li> </ul> </section> </div> ); }