Listák és kulcsok
Először is vegyük át hogyan alakítunk át listákat JavaScript-ben.
Vegyük az alábbi kódot. A map()
függvény fog egy számokkal teli tömböt (numbers
) és megduplázza annak értékeit. A map()
által visszaadott új tömböt hozzárendeljük a doubled
változóhoz, és kiírjuk a konzolba:
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);console.log(doubled);
Ez a kód a [2, 4, 6, 8, 10]
tömböt írja ki a konzolba.
A React-ben tömböket elemlistákká majdnem ugyanígy transzformálunk.
Komponensek többszöri renderelése
Elemkollekciókat kapcsos zárójelek segítségével {}
készíthetsz és illeszthetsz JSX-be.
Az alábbiakban egy numbers
tömbön iterálunk végig a map()
függvény használatával. Minden elemhez visszaadunk egy <li>
elemet. Végül hozzárendeljük a kapott elemek tömbjét a listItems
-hez:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);
A listItems
tömböt belefoglaljuk egy <ul>
elembe, és azt a DOM-ba rendereljük:
ReactDOM.render(
<ul>{listItems}</ul>, document.getElementById('root')
);
Ez a kód egy pontokba szedett számlistát mutat 1-től 5-ig.
Alap lista komponens
Listákat általában egy komponensbe szeretnénk renderelni.
Az előző példát át tudjuk alakítani egy komponenssé, ami fogad egy numbers
tömböt, és egy elemlistát ad vissza.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <li>{number}</li> ); return (
<ul>{listItems}</ul> );
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />, document.getElementById('root')
);
Ha ezt a kódot futtatod, egy figyelmeztetést fogsz kapni, hogy minden listaelemnek rendelkeznie kell egy kulccsal. A “key” (kulcs) egy speciális szöveges attribútum, amit fel kell vegyél ha listaelemeket készítesz. A következő szekcióban megbeszéljük hogy ez miért is fontos.
Rendeljünk hozzá egy key
-t a listaelemeinkhez a numbers.map()
-en belül, hogy kijavítsuk a kulcs problémát.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
Kulcsok
A kulcsok segítenek a React-nek azonosítani, hogy mely elemek változtak, lettek hozzáadva, vagy épp törölve. A kulcsokat a tömbön belül kell az elemekhez hozzárendelnünk a stabil azonosíthatóság érdekében:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
A legjobb módja egy kulcs választásának ha egy szöveget használunk, ami egyedien azonosít egy listaelemet annak testvérei között. Leggyakrabban az adatod ID azonosítókulcsa lehet a legjobb kulcs:
const todoItems = todos.map((todo) =>
<li key={todo.id}> {todo.text}
</li>
);
Ha nincs egy stabil ID azonosítókulcsod a renderelt elemekhez, akkor használhatod az elemindexet is kulcsként utolsó lehetőségként:
const todoItems = todos.map((todo, index) =>
// Csak akkor tedd ezt, ha nincs egy stabil ID azonosítókulcsod <li key={index}> {todo.text}
</li>
);
Ha az elemek sorrendje változhat, akkor nem ajánljuk indexek használatát kulcsként. Ez negatívan hathat ki a teljesítményre és problémákat okozhat a komponens állapotában. Nézd meg Robin Pokorny’ cikkét egy mélyebbre ható magyarázatért, az index mint kulcs használatáról. Ha úgy döntesz, hogy nem rendelsz egy explicit kulcsot a listaelemekhez, a React automatikusan az indexet fogja kulcsként használni.
Itt egy mélyebbre ható magyarázat, hogy miért is fontosak a kulcsok ha többet szeretnél tanulni.
Komponensek kivonása kulcsokkal
A kulcsoknak csak a környező tömb kontextusában van értelmük.
Például ha kivonsz egy ListItem
komponenst, a kulcsot a <ListItem />
elemen kell hogy tartsd, nem pedig áttenni azt az <li>
elemre a ListItem
-en belül.
Példa: Helytelen kulcshasználat
function ListItem(props) {
const value = props.value;
return (
// Hibás! Itt a kulcs definiálásának nincs semmi értelme: <li key={value.toString()}> {value}
</li>
);
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Hibás! A kulcsot itt kell definiálni: <ListItem value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
Példa: Helyes kulcshasználat
function ListItem(props) {
// Helyes! Itt a kulcs definiálásának nincs semmi értelme: return <li>{props.value}</li>;}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Helyes! A kulcsot itt kell definiálni: <ListItem key={number.toString()} value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
Egy jó ökölszabály, hogy a map()
-en belül lévő minden elemnek rendelkeznie kell egy kulccsal.
A kulcsoknak csak testvéreik között kell egyedinek lenniük
A kulcsoknak egyedinek kell lenniük testvéreik között. Azonban nem kell, hogy globálisan is egyediek legyenek. Ugyanazokat a kulcsokat használhatjuk két különböző tömb készítése esetén:
function Blog(props) {
const sidebar = ( <ul>
{props.posts.map((post) =>
<li key={post.id}> {post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) => <div key={post.id}> <h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar} <hr />
{content} </div>
);
}
const posts = [
{id: 1, title: 'Helló, világ', content: 'Üdövzlünk a React tanulói kurzusában!'},
{id: 2, title: 'Telepítés', content: 'A React-et npm-ből tudod telepíteni.'}
];
ReactDOM.render(
<Blog posts={posts} />,
document.getElementById('root')
);
A kulcsok a React számára szolgálnak utalásként, de leküldve nem lesznek a komponenseidnek. Ha ugyanarra az értékre van szükséged a komponensedben is, akkor azt egy másik prop névvel is explicit módon meg kell adnod:
const content = posts.map((post) =>
<Post
key={post.id} id={post.id} title={post.title} />
);
A fenti példával a Post
komponens olvasni tudja props.id
-t, de a props.key
-t nem.
map() JSX-be ágyazása
A fenti példákban külön deklaráltuk a listItems
változót és belevettük azt a JSX-be:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <ListItem key={number.toString()} value={number} /> ); return (
<ul>
{listItems}
</ul>
);
}
A JSX lehetővé teszi bármilyen kifejezés beágyazását kapcsos zárójelek között, így a map()
eredményét is:
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul>
);
}
Ennek néha tisztább kód az eredménye, de ezzel a stílussal könnyű visszaélni. Ahogy a JavaScript-ben is, tőled függ hogy megéri-e kivonni egy változót az olvashatóság érdekében. Tartsd észben hogy ha a map()
teste túl beágyazott, talán itt az ideje kivonni egy komponenst.