Prosleđivanje props-a u komponentu
React komponente koriste props da bi međusobno komunicirale. Svaka roditeljska komponenta može proslediti informacije svojoj deci tako što im daje props. Props-i vas možda podsećaju na HTML atribute, ali pomoću njih možete proslediti bilo koju JavaScript vrednost, uključujući objekte, nizove i funkcije.
Naučićete:
- Kako da prosledite props-e u komponentu
- Kako da pročitate props-e u komponenti
- Kako da definišete default vrednosti za props
- Kako da prosledite JSX komponenti
- Kako se props-i menjaju tokom vremena
Poznati props-i
Props-i su informacije koje prosleđujete u JSX tag. Na primer, className
, src
, alt
, width
i height
su samo neki od props-a koje možete proslediti u <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 /> ); }
Props-i koje prosleđujete u <img>
tag su predefinisani (ReactDOM se prilagođava HTML standardu). Vi možete proslediti bilo koji props vašim komponentama, poput <Avatar>
-a, da biste ih prilagodili svojim potrebama. Evo i kako!
Prosleđivanje props-a u komponentu
U ovom primeru, Profile
komponenta ne prosleđuje nikakav props svom detetu, Avatar
komponenti:
export default function Profile() {
return (
<Avatar />
);
}
U dva koraka možete dodati props u Avatar
.
Korak 1: Proslediti props u dete komponentu
Prvo, prosledite props u Avatar
. Na primer, prosledimo dva props-a: person
(objekat) i size
(broj):
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
Sada ove props-e možete pročitati unutar Avatar
komponente.
Korak 2: Pročitati props unutar dečje komponente
Možete pročitati ove props-e izlistavanjem njihovih imena person, size
odvojenih zarezima unutar ({
i })
odmah nakon function Avatar
. Ovo vam omogućava da ih koristite unutar Avatar
funkcije, kao bilo koju drugu promenljivu.
function Avatar({ person, size }) {
// person i size su dostupni ovde
}
Dodajte neku logiku u Avatar
koja će koristiti person
i size
props-e za renderovanje i gotovi ste.
Sada možete konfigurisati Avatar
da renderuje različite stvari uz pomoć različitih props-a. Probajte da menjate vrednosti!
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> ); }
Props-i vam omogućavaju da odvojeno razmišljate o roditeljskim i dečjim komponentama. Na primer, možete promeniti person
ili size
props unutar Profile
-a bez potrebe da razmišljate kako ih Avatar
koristi. Slično tome, možete promeniti kako Avatar
koristi te props-e bez gledanja u Profile
.
Props-e možete zamisliti kao “dugmiće” koje možete podešavati. Oni igraju istu ulogu kao i argumenti u funkcijama—u suštini, props-i jesu jedini argument u vašoj komponenti! Funckije React komponenata prihvataju samo jedan argument, props
objekat:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
Uglavnom vam neće biti potreban ceo props
objekat, već ćete ga dekonstruisati na pojedinačne props-e.
Definisanje default vrednosti za prop
Ako želite da zadate default vrednost prop-u, koja će se koristiti kada vrednost nije definisana, to možete uraditi pomoću dekonstruisanja stavljajući =
i default vrednost odmah nakon parametra:
function Avatar({ person, size = 100 }) {
// ...
}
Sada, ako se <Avatar person={...} />
renderuje bez size
prop-a, size
će biti setovano na 100
.
Default vrednost je upotrebljena samo ako izostavite size
prop ili ako prosledite size={undefined}
. Ali, ako prosledite size={null}
ili size={0}
, default vrednost neće biti upotrebljena.
Prosleđivanje props-a sa JSX spread sintaksom
Ponekad se prosleđivanje props-a može ponavljati:
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
Nema ništa loše u ponavljanju koda—ponekad može biti čitljivije. Ali, nekada vam je potrebna sažetost. Neke komponente prosleđuju sve svoje props-e deci, kao što to Profile
radi sa Avatar
-om. Pošto one direktno ne koriste nijedan svoj prop, ima smisla upotrebiti koncizniju “spread” sintaksu:
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
Ovo prosleđuje sve props-e od Profile
-a u Avatar
bez izlistavanja njihovih imena pojedinačno.
Koristite spread sintaksu odmereno. Ako je koristite u svakoj komponenti, nešto nije u redu. To često označava da biste trebali podeliti komponente i proslediti decu kao JSX. Više u nastavku!
Prosleđivanje JSX-a kao dece
Ugnježdavanje ugrađenih (built-in) tag-ova je često:
<div>
<img />
</div>
Ponekad želite da ugnjezdite vaše komponente na isti način:
<Card>
<Avatar />
</Card>
Kada ugnjezdite sadržaj unutar JSX tag-a, roditeljska komponenta će primiti taj sadržaj kroz prop po imenu children
. Na primer, Card
komponenta ispod će primiti children
prop setovan na <Avatar />
i renderovati ga u wrapper div-u:
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> ); }
Pokušajte da promenite <Avatar>
unutar <Card>
-a sa nekim tekstom da biste videli kako Card
komponenta može da obmota bilo koji ugnježdeni sadržaj. Ona ne mora da “zna” šta će biti renderovano unutar nje. Videćete ovaj fleksibilni obrazac na mnogim mestima.
Komponentu sa children
prop možete zamisliti kao da ima “šupljinu” koja će biti “popunjena” u njenim roditeljskim komponentama sa proizvoljnim JSX-om. Često ćete koristiti children
prop za vizuelne wrapper-e: panel-e, grid-ove, itd.
Illustrated by Rachel Lee Nabors
Kako se props-i menjaju tokom vremena
Clock
komponenta ispod prima dva props-a od svog roditelja: color
i time
. (Kod roditeljske komponente je izostavljen zato što koristi state, u koji nećemo zalaziti još uvek.)
Pokušajte da promenite boju u primeru ispod:
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
Ovaj primer ilustruje kako komponenta može primiti različite props-e tokom vremena. Props-i nisu uvek statički! Ovde se time
prop menja svake sekunde, a color
prop se menja kada odaberete drugu boju. Props-i odražavaju podatke u komponenti u bilo kom trenutku, a ne samo na početku.
Međutim, props-i su immutable—pojam koji u informatici označava nešto “nepromenljivo”. Kada komponenta treba da promeni svoje props-e (na primer, nakon interakcije korisnika ili na osnovu novih podataka), moraće da “pita” svog roditelja da joj prosledi druge props-e—novi objekat! Njeni stari props-i će biti odbačeni, a JavaScript će se u nekom trenutku pobrinuti da oslobodi memoriju koju su zauzeli.
Ne pokušavajte da “menjate props”. Kada želite da reagujete na korisnički input (kao što je promena odabrane boje), moraćete da “set-ujete state”, što možete naučiti u State: Memorija komponente.
Recap
- Da biste prosledili props, dodajte ih u JSX, kao što bi to uradili sa HTML atributima.
- Da biste pročitali props, koristite
function Avatar({ person, size })
sintaksu dekonstruisanja. - Možete definisati default vrednost poput
size = 100
, koja se koristi za izostavljene iundefined
props-e. - Možete proslediti sve props-e sa
<Avatar {...props} />
JSX spread sintaksom, ali nemojte je previše koristiti! - Ugnježdeni JSX poput
<Card><Avatar /></Card>
će se pojaviti uCard
komponenti kaochildren
prop. - Props-i su read-only snapshot-ovi u vremenu: svako renderovanje prima novu verziju props-a.
- Ne možete menjati props-e. Kada vam je potrebna interaktivnost, trebate da setujete state.
Izazov 1 od 3: Izdvojiti komponentu
Ova Gallery
komponenta sadrži veoma sličan markup za dva profila. Izdvojite Profile
komponentu kako biste smanjili ponavljanje. Moraćete da izaberete koje props-e da joj prosledite.
import { getImageUrl } from './utils.js'; export default function Gallery() { return ( <div> <h1>Značajni naučnici</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>Profesija: </b> fizičar i hemičar </li> <li> <b>Nagrade: 4 </b> (Nobelova nagrada za fiziku, Nobelova nagrada za hemiju, Davy medalja, Matteucci medalja) </li> <li> <b>Otkrića: </b> polonijum (hemijski 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>Profesija: </b> geohemičar </li> <li> <b>Nagrade: 2 </b> (Miyake nagrada za geohemiju, Tanaka nagrada) </li> <li> <b>Otkrića: </b> metoda za merenje ugljen-dioksida u morskoj vodi </li> </ul> </section> </div> ); }