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.

  1. 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'
];
  1. Map metodu ile people üyelerini listItems adında yeni bir JSX node dizisine atayın:
const listItems = people.map(person => <li>{person}</li>);
  1. Return ifadesini kullanarak <ul> elementi içinde listItems’ı döndürün:
return <ul>{listItems}</ul>;

İşte sonuç:

const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

export default function List() {
  const listItems = people.map(person =>
    <li>{person}</li>
  );
  return <ul>{listItems}</ul>;
}

Yukarıdaki sandbox’un bir konsol hatası gösterdiğine dikkat edin:

Console
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:

  1. Sadece “chemist” mesleğindeki insanlardan yeni bir chemists dizisi oluştur, bunun için filter() metodunu people dizisinde person.profession === 'chemist' şeklinde kullanabilirsin:
const chemists = people.filter(person =>
person.profession === 'chemist'
);
  1. Şimdi chemists dizisinde 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>
);
  1. Son olarak, bileşeninizden listItems dö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:

Console
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, // JSX için anahtar olarak kullanılır
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
  accomplishment: 'spaceflight calculations',
  imageId: 'MK3eW3A'
}, {
  id: 1, // JSX için anahtar olarak kullanılır
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
  accomplishment: 'discovery of Arctic ozone hole',
  imageId: 'mynHUSa'
}, {
  id: 2, // JSX için anahtar olarak kullanılır
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
  accomplishment: 'electromagnetism theory',
  imageId: 'bE7W1ji'
}, {
  id: 3, // JSX için anahtar olarak kullanılır
  name: 'Percy Lavon Julian',
  profession: 'chemist',
  accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
  imageId: 'IOjWm71'
}, {
  id: 4, // JSX için anahtar olarak kullanılır
  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 da uuid gibi 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 anahtar neden ve nasıl kullanılır.

Problem 1 / 4:
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>
  );
}