Renderovanje listi
Često ćete želeti da prikažete više sličnih komponenata iz kolekcije podataka. Možete koristiti JavaScript metode za nizove kako bi manipulisali nizovima podataka. U ovom članku, koristićete filter()
i map()
da uz React filtrirate i transformišete vaš niz podataka u niz komponenata.
Naučićete:
- Kako da renderujete komponente na osnovu niza uz pomoć JavaScript-ovog
map()
-a - Kako da renderujete samo specifične komponente uz pomoć JavaScript-ovog
filter()
-a - Kada i zašto da koristite React ključeve
Renderovanje podataka iz nizova
Recimo da imate sledeću listu.
<ul>
<li>Creola Katherine Johnson: matematičar</li>
<li>Mario José Molina-Pasquel Henríquez: hemičar</li>
<li>Mohammad Abdus Salam: fizičar</li>
<li>Percy Lavon Julian: hemičar</li>
<li>Subrahmanyan Chandrasekhar: astrofizičar</li>
</ul>
Jedina razlika u stavkama liste je njihov sadržaj, njihovi podaci. Često ćete imati potrebu da prikažete nekoliko instanci iste komponente sa drugačijim podacima kada pravite interfejse: od liste komentara do galerije profilnih slika. U takvim situacijama, možete čuvati podatke u JavaScript objektima i nizovima i upotrebiti metode kao što su map()
i filter()
da od njih renderujete listu komponenata.
Evo kratkog primera kako da generišete listu stavki na osnovu niza:
- Pomerite podatke u niz:
const people = [
'Creola Katherine Johnson: matematičar',
'Mario José Molina-Pasquel Henríquez: hemičar',
'Mohammad Abdus Salam: fizičar',
'Percy Lavon Julian: hemičar',
'Subrahmanyan Chandrasekhar: astrofizičar'
];
- Mapirajte
people
članove u novi niz JSX čvorova,listItems
:
const listItems = people.map(person => <li>{person}</li>);
- Vratite
listItems
iz vaše komponente umotano u<ul>
:
return <ul>{listItems}</ul>;
Evo rezultata:
const people = [ 'Creola Katherine Johnson: matematičar', 'Mario José Molina-Pasquel Henríquez: hemičar', 'Mohammad Abdus Salam: fizičar', 'Percy Lavon Julian: hemičar', 'Subrahmanyan Chandrasekhar: astrofizičar' ]; export default function List() { const listItems = people.map(person => <li>{person}</li> ); return <ul>{listItems}</ul>; }
Primetite da sandbox iznad prikazuje grešku u konzoli:
Naučićete kako da popravite grešku malo kasnije u ovom članku. Pre toga, hajde da malo strukturiramo podatke.
Filtriranje niza stavki
Ovi podaci mogu dodatno biti strukturirani.
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'matematičar',
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'hemičar',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'fizičar',
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'hemičar',
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrofizičar',
}];
Recimo da želite pronaći način da prikažete samo ljude čija je profesija 'hemičar'
. Možete koristiti JavaScript-ovu filter()
metodu da vratite samo te ljude. Ova metoda prima niz stavki, propušta ih kroz “test” (funkcija koja vraća true
ili false
), i vraća novi niz samo onih stavki koje su prošle test (vraćeno je true
).
Želite samo stavke gde je profession
jednako 'hemičar'
. Ta “test” funkcija u ovom slučaju izgleda (person) => person.profession === 'hemičar'
. Evo kako to možete uraditi:
- Napravite novi niz samo “hemičara”,
chemists
, pozivanjemfilter()
nadpeople
i filtriranjemperson.profession === 'hemičar'
:
const chemists = people.filter(person =>
person.profession === 'hemičar'
);
- Sada mapirajte kroz
chemists
:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
poznat je zbog {person.accomplishment}
</p>
</li>
);
- Na kraju, vratite
listItems
iz vaše komponente:
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 === 'hemičar' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} poznat je zbog {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
Čuvanje redosleda stavki u listi sa key
Primetite da svi sandbox-ovi iznad prikazuju grešku u konzoli:
Svakom članu niza morate dodeliti key
— string ili broj koji ga jedinstveno identifikuje u tom nizu:
<li key={person.id}>...</li>
Ključevi govore React-u koji član niza odgovara kojoj komponenti, kako bi mogao kasnije da ih poveže. Ovo postaje značajno ako članovi niza mogu da se pomeraju (npr. prilikom sortiranja), ubacuju, ili brišu. Dobro odabran key
pomaže React-u da zaključi šta se zapravo dogodilo, kako bi ispravno mogao da ažurira DOM stablo.
Umesto da generišete ključeve u hodu, trebalo bi da ih uključite u vaše podatke:
export const people = [{ id: 0, // Koristi se u JSX kao ključ name: 'Creola Katherine Johnson', profession: 'matematičar', accomplishment: 'formula za svemirske letove', imageId: 'MK3eW3A' }, { id: 1, // Koristi se u JSX kao ključ name: 'Mario José Molina-Pasquel Henríquez', profession: 'hemičar', accomplishment: 'otkriće Arktičke rupe u ozonu', imageId: 'mynHUSa' }, { id: 2, // Koristi se u JSX kao ključ name: 'Mohammad Abdus Salam', profession: 'fizičar', accomplishment: 'teorija o elektromagnetizmu', imageId: 'bE7W1ji' }, { id: 3, // Koristi se u JSX kao ključ name: 'Percy Lavon Julian', profession: 'hemičar', accomplishment: 'pionirski kortizon, steroidi i pilule za kontrolu rađanja', imageId: 'IOjWm71' }, { id: 4, // Koristi se u JSX kao ključ name: 'Subrahmanyan Chandrasekhar', profession: 'astrofizičar', accomplishment: 'računanje mase belog patuljka', imageId: 'lrWQx8l' }];
Deep Dive
Šta raditi kad svaka stavka u listi treba renderovati ne jedan, već nekoliko DOM čvorova?
Kratka <>...</>
Fragment sintaksa vam ne dopušta da prosledite ključ, tako da ih morate grupisati u jedan <div>
, ili prosto upotrebiti malo dužu i eksplicitniju <Fragment>
sintaksu:
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Fragment-i nestaju iz DOM-a, tako da ćete dobiti listu od <h1>
, <p>
, <h1>
, <p>
, i tako dalje.
Gde dobiti key
Različiti izvori podataka pružaju različite ključeve:
- Podaci iz baze podataka: Ako podaci dolaze iz baze podataka, možete koristiti ključeve ili ID-eve iz baze podataka, koji su po prirodi jedinstveni.
- Lokalno generisani podaci: Ako su vam podaci generisani i čuvani lokalno (npr. beleške u aplikaciji za zabeleške), koristite inkrementalni brojač,
crypto.randomUUID()
ili pakete poputuuid
kada kreirate stavke.
Pravila ključeva
- Ključevi moraju biti jedinstveni između „sestrinskih” stavki. Međutim, u redu je koristiti iste ključeve za JSX čvorove u različitim nizovima.
- Ključevi se ne smeju menjati ili će im se svrha obesmisliti! Nemojte ih generisati tokom renderovanja.
Zašto su React-u potrebni ključevi?
Zamislite da fajlovi na vašem desktop-u nemaju imena. Umesto toga, referencirali bi ih po njihovom redosledu — prvi fajl, drugi fajl, i tako dalje. Mogli biste se navići, ali jednom kada obrišete fajl, postalo bi zbunjujuće. Drugi fajl bi postao prvi fajl, treći fajl bi postao drugi fajl, i tako dalje.
Imena fajlova u folderu i JSX ključevi imaju sličnu ulogu. Omogućavaju nam da jedinstveno identifikujemo stavku među „sestrinskim” stavkama. Dobro odabran ključ pruža više informacija od puke pozicije u nizu. Čak iako se pozicija promeni zbog promene redosleda, key
omogućava React-u da identifikuje stavku tokom njenog životnog veka.
Recap
Na ovoj stranici naučili ste:
- Kako da premestite podatke iz komponenti u strukture podataka poput nizova i objekata.
- Kako da generišete setove sličnih komponenata pomoću JavaScript-ovog
map()
-a. - Kako da kreirate nizove filtriranih stavki pomoću JavaScript-ovog
filter()
-a. - Zašto i kako da postavite
key
za svaku komponentu u kolekciji, kako bi React mogao da prati svaku od njih, čak iako im se pozicija ili podaci promene.
Izazov 1 od 4: Podeliti listu na dva dela
Ovaj primer prikazuje listu svih ljudi.
Promenite ga da prikazuje dve odvojene liste jednu za drugom: Hemičari i Svi ostali. Kao i ranije, možete odrediti da li je osoba hemičar sledećim uslovom person.profession === 'hemičar'
.
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 + ' '} poznat je zbog {person.accomplishment} </p> </li> ); return ( <article> <h1>Naučnici</h1> <ul>{listItems}</ul> </article> ); }