Listeleri Render Etmek – React
Genellikle bir veri topluluğundan birden fazla benzer bileşen göstermek isteyeceksiniz. Bir veri dizisini manipule etmek için JavaScript dizi metodlarını kullanabilirsiniz. Bu sayfada, React ile filter() ve map() metodlarını kullanarak bir veri dizisini filtreleyecek ve bir bileşen dizisine dönüştüreceksiniz.
Bunları öğreneceksiniz
- Javascript’in
map()metodunu kullanarak bir diziden nasıl bileşenler oluşturulur? - Javascript’in
filter()metodunu kullanarak yalnızca belirli bileşenler nasıl oluşturulur? - React anahtarlarını ne zaman ve neden kullanmalıyız?
Dizilerden veri render etmek
Aşağıdaki gibi bir listeniz olduğunu düşünelim.
<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>
Bu liste öğeleri arasındaki tek fark içerikleri, verileridir. Arayüzler oluştururken farklı veriler kullanan aynı bileşenin birkaç örneğini göstermeniz gerekebilir: yorum listeleri ya da profil resimleri galerileri gibi. Bu gibi durumlarda, gerekli verileri Javascript objeleri ve dizilerinde saklayabilir ve map() ve filter() gibi metodları kullanarak bu verilerden bileşen listeleri oluşturabilirsiniz.
Aşağıdaki kısa örnekte bir diziden nasıl öğe listesi oluşturulduğunu görebilirsiniz.
- Verinizi bir dizi içine aktarın:
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist'
];
- Map metodu ile
peopleüyelerinilistItemsadında yeni bir JSX node dizisine atayın:
const listItems = people.map(person => <li>{person}</li>);
- Return ifadesini kullanarak
<ul>elementi içindelistItems’ı döndürün:
return <ul>{listItems}</ul>;
İşte sonuç:
Yukarıdaki sandbox’un bir konsol hatası gösterdiğine dikkat edin:
Uyarı: Bir listedeki her alt elemanın benzersiz bir “key” (“anahtar”) prop’u olmalıdır.
Bu hatayı daha sonra bu sayfada nasıl düzelteceğinizi öğreneceksiniz. Buna gelmeden önce, verilerinize biraz yapı ekleyelim.
Bir diziyi filtreleme
Bu veriler daha da yapılandırılabilir.
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',
}];
Diyelim ki sadece mesleği 'chemist' olan kişileri göstermenin bir yolunu istiyorsunuz. Javacript’in filter() metodunu kullanarak yalnızca bu kişileri döndürebilirsiniz. Bu yöntem, bir diziyi alır, onları bir “testten” (doğru veya yanlış döndüren bir test) geçirir ve yalnızca testi geçen (doğru olarak döndürülen) öğelerden oluşan yeni bir dizi oluşturur.
Sadece mesleği 'chemist' olan kişileri istiyorsunuz. Bunun için “test” fonksiyonu (person) => person.profession === 'chemist' şeklindedir. Bunu nasıl bir araya getireceğiniz aşağıda gösterilmiştir:
- Sadece “chemist” mesleğindeki insanlardan yeni bir
chemistsdizisi oluştur, bunun içinfilter()metodunupeopledizisindeperson.profession === 'chemist'şeklinde kullanabilirsin:
const chemists = people.filter(person =>
person.profession === 'chemist'
);
- Şimdi
chemistsdizisinde map metodu kullanılır:
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>
);
- Son olarak, bileşeninizden
listItemsdöndürülür:
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>; }
Tuzak
Ok fonksiyonları, ”=>” ifadesinden sonra ifadeyi hemen döndürür, böylece bir return ifadesine ihtiyacınız olmaz:
const listItems = chemists.map(person =>
<li>...</li> // Implicit return!
);
Ancak, => ifadesinden sonra { parentezini kullandıysanız, return ifadesini yazmak zorundasınız
const listItems = chemists.map(person => { // Curly brace
return <li>...</li>;
});
=> { içeren ok fonksiyonların bir “blok gövdesi”. olduğu söylenir. Ok fonksiyonları tek bir kod satırından daha fazlasını yazmanıza olanak verir ancak return ifadesini yazmanız gerekmektedir. Eğer unutursanız, fonksiyonunuz geri hiçbir şey döndürmez!
key (anahtar) prop’u ile liste öğelerini sıralı şekilde tutmak
Yukarıdaki tüm sandbox’ların konsolda bir hata gösterdiğine dikkat edin:
Uyarı: Bir listedeki her alt elemanın benzersiz bir “key” (“anahtar”) prop’u olmalıdır.
Her bir dizi öğesine bir key (anahtar) vermelisiniz — dizideki her bir öğeyi birbirinden ayırt edecek şekilde o öğeye bir string ya da numara vermeniz gerekmektedir:
<li key={person.id}>...</li>
Not
Her map() metodu kullanıldığında JSX elementleri bir anahtara ihtiyaç duyar.
Anahtarlar, React’e her bir bileşenin hangi dizi öğesine karşılık geldiğini söylerek React’in daha sonra bu öğeleri eşleştirmesini sağlar. Bu durum, eğer dizi öğeleriniz yer değiştiriyorsa (örneğin sıralaması değişiyorsa), yeni öğeler eklenip veya çıkartılabiliyorsa daha önemli bir hale gelir. İyi seçilmiş bir anahtar React’in değişen öğelerde ne olduğunu anlamasına ve DOM ağacında doğru güncellemeleri yapmasına yardımcı olur.
Anında anahtar oluşturmak yerine, anahtarları verilerinize dahil etmelisiniz:
export const people = [{ id: 0, name: 'Creola Katherine Johnson', profession: 'mathematician', accomplishment: 'spaceflight calculations', imageId: 'MK3eW3A' }, { id: 1, name: 'Mario José Molina-Pasquel Henríquez', profession: 'chemist', accomplishment: 'discovery of Arctic ozone hole', imageId: 'mynHUSa' }, { id: 2, name: 'Mohammad Abdus Salam', profession: 'physicist', accomplishment: 'electromagnetism theory', imageId: 'bE7W1ji' }, { id: 3, name: 'Percy Lavon Julian', profession: 'chemist', accomplishment: 'pioneering cortisone drugs, steroids and birth control pills', imageId: 'IOjWm71' }, { id: 4, name: 'Subrahmanyan Chandrasekhar', profession: 'astrophysicist', accomplishment: 'white dwarf star mass calculations', imageId: 'lrWQx8l' }];
Derinlemesine İnceleme
Her liste öğesi için birkaç DOM node’u göstermek
Her öğenin bir değil birkaç DOM node’u render etmesi gerektiğinde ne yaparsınız?
Kısa <>...</> Fragment syntax’ı bir key (anahtar) prop’u belirlemenize izin vermez, bu nedenle tüm elementleri bir <div> elementi içinde gruplandırmanız ya da daha uzun olan <Fragment> syntax’i kullanmalısınız.
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Fragmentler DOM’dan kaybolur, bu nedenle geriye sadece <h1>, <p>, <h1>, <p> gibi elementler kalacaktır.
anahtar nereden gelir
Farklı veri kaynakları, farklı anahtar kaynakları sağlar:
- Veritabanından gelen veri: Eğer veriniz bir veritabanından geliyorsa, doğasından ötürü zaten benzersiz olan veritabanı anahtarları/ID’leri kullanılabilir.
- Yerel olarak oluşturulmuş veriler: Eğer veriniz yerel olarak oluşturuluyor ve saklanıyorsa (örneğin not alma aplikasyonundaki notlar), sıralı olarak artan numaralar
crypto.randomUUID()ya dauuidgibi bir paket kullanabilirsiniz.
Anahtarların kuralları
- Anahtarlar kardeşler arasında benzersiz olmalıdır. Ancak, farklı dizilerdeki JSX node’ları için aynı anahtarları kullanmakta bir sakınca yoktur.
- Anahtarlar değişmemelidir. yoksa bu anahtarların bütün amacını bozar! Anahtarları render etme sırasında üretmeyiniz.
React neden anahtarlara ihtiyaç duyar?
Masaüstünüzdeki dosyaların isimlerinin olmadığını düşünün. Bunun yerine, dosyalara sıralarına göre referans edersiniz — ilk dosya, ikinci dosya gibi. Bu sisteme alışabilirsiniz ama bir dosyayı sildiğiniz zaman durum kafa karıştırıcı bir hale gelecektir. İkinci dosya birinci, üçüncü dosya ise ikinci dosya olurdu gibi.
Dosya isimleri de dizilerdeki JSX anahtarları gibi aynı amaca hizmet etmektedir. Anahtarlar, kardeşleri arasında bir öğeyi benzersiz bir şekilde tanımlamamıza olanak sağlar. İyi seçilmiş bir anahtar, dizi içindeki pozisyondan daha fazla bilgi sağlar. Örneğin sıra yeniden sıralama nedeniyle değişse bile, anahtar React’in öğeyi döngü boyunca tanımasını sağlar.
Tuzak
Anahtar olarak dizideki bir öğenin indeksini kullanmak isteyebilirsiniz. Aslında, hiç bir key (anahtar) belirtmezseniz React’in kullanacağı anahtar bu olacaktır. Ancak, bir öğe eklenirse, silinirse veya dizi yeniden sıralanırsa, öğeleri oluşturma sıranız zaman içinde değişecektir. Bir anahtar olarak indeksi kullanmak, genellikle gizli ve kafa karıştırıcı hatalara yol açar.
Benzer şekilde, anahtarları o anda oluşturmayın, örneğin key={Math.random()} ile oluşturulan anahtarlar. Bu, anahtarların render etmeler arasında eşleşmemesine neden olarak tüm bileşenlerinizin ve DOM’un her seferinde yeniden oluşturulmasına yol açar. Bu sadece yavaş olmakla kalmaz, aynı zamanda liste öğeleri içindeki herhangi bir kullanıcı girdisini de kaybeder. Bunun yerine, verilere dayalı sabit bir ID kullanılmalıdır.
Bileşenlerinizin prop olarak key (anahtar) almayacağını unutmayın. Yalnıcaz React’in kendisi tarafından bir işaret olarak kullanılırlar. Eğer bileşeninizin bir ID’ye ihtiyacı varsa, ID’yi ayrı bir prop olarak şu şekilde kullanabilirsiniz: <Profile key={id} userId={id} />.
Özet
Bu sayfada şunları öğrendiniz:
- Verileri bileşenlerin dışına, diziler ve objeler gibi veri yapılarına taşıma.
- JavaScript’in
map()metodu ile benzer bileşen setleri oluşturma. - JavaScript’in
filter()metodu ile filterenmiş öğe dizileri oluşturma. - React’in, konumları ya da verileri değişse bile her bir koleksiyondaki her bileşeni takip edebilmesi için
anahtarneden ve nasıl kullanılır.
Bir listeyi ikiye bölme
Bu örnek tüm insanların bir listesini göstermektedir.
Örneği birbiri ardına iki ayrı liste gösterecek şekilde değiştirin: Chemists ve Everyone Else. Daha önce yaptığımız gibi, bir insanın “chemist” olup olmadığını person.profession === 'chemist' ifadesi ile tespit edebilirsiniz.
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> ); }