React bileşenleri, birbirleriyle iletişim kurmak için prop’ları kullanır. Her üst eleman, alt elemanlarına prop’lar vererek onlarla bilgi paylaşabilir. Prop’lar, size HTML özelliklerini hatırlatabilir, ancak onların aracılığıyla nesneler, diziler ve fonksiyonlar da dahil olmak üzere herhangi bir JavaScript değeri aktarabilirsiniz.

Bunları öğreneceksiniz

  • Bileşene prop nasıl aktarılır
  • Bir bileşenden prop nasıl okunur
  • Prop’lar için varsayılan değerler nasıl belirlenir
  • Bir bileşene JSX nasıl aktarılır
  • Prop’ların zamanla nasıl değiştiği

Tanıdık Prop’lar

Prop’lar, JSX etiketine ilettiğiniz bilgilerdir. Örneğin, className, src, alt, width ve height, bir <img>’ye aktarabileceğiniz prop’lardan bazılarıdır:

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 />
  );
}

Bir <img> etiketine aktarabileceğiniz prop’lar önceden tanımlanmıştır (ReactDOM, HTML standardına uygundur). Ancak, özelleştirmek için <Avatar> gibi kendi bileşenlerinize herhangi bir özellik aktarabilirsiniz. İşte nasıl!

Bileşene prop’lar aktarma

Bu kodda, Profile bileşeni, Avatar adlı alt bileşenine herhangi bir prop aktarmıyor:

export default function Profile() {
return (
<Avatar />
);
}

Avatar’a iki adımda prop’lar ekleyebilirsiniz.

Adım 1: Alt bileşene prop’lar aktarma

Öncelikle, Avatar’a bazı prop’lar ekleyin. Örneğin, iki prop ekleyelim: person (bir nesne) ve size (bir sayı):

export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}

Not

Eğer person= sonrasındaki çift süslü parantezler sizi şaşırtırsa, bunların JSX süslü parantezlerinin içinde sadece bir nesne olduklarını hatırlayın.

Şimdi bu prop’ları Avatar bileşeni içinde okuyabilirsiniz.

Adım 2: Alt eleman içinde prop’ları okuma

Bu prop’ları, function Avatar’dan hemen sonra ({ ve }) içinde virgülle ayrılan person, size isimlerini yazarak okuyabilirsiniz. Bu, onları Avatar kodunun içinde bir değişken gibi kullanmanıza olanak tanır.

function Avatar({ person, size }) {
// burada person ve size kullanılabilir
}

Avatar’a, person ve size prop’larını kullanarak render etmek için biraz mantık ekleyin ve hazırsınız.

Artık Avatar’ı farklı prop’larla birçok farklı şekilde render etmek için yapılandırabilirsiniz. Değerler ile oynamayı deneyin!

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>
  );
}

Prop’lar, üst ve alt bileşenleri bağımsız olarak düşünmenize olanak tanır. Örneğin, Avatar’ın bunları nasıl kullandığını düşünmeden, Profile içindeki person veya size prop’larını değiştirebilirsiniz. Benzer şekilde, Profile’a bakmadan, Avatar’ın bu prop’ları nasıl kullandığını değiştirebilirsiniz.

Prop’ları ayarlayabileceğiniz “düğmeler” gibi düşünebilirsiniz. Aslında, prop’lar fonksiyonlara sağlanan argümanlarla aynı rolü üstlenirler - aslında, prop’lar bileşeniniz için tek argümanlardır! React bileşen fonksiyonları, bir props nesnesi olarak tek bir argümanı kabul ederler:

function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}

Genellikle tüm props nesnesine ihtiyacınız olmaz, bu yüzden onu bireysel prop’lara ayırarak yapıyı çözmeniz gerekir.

Tuzak

Prop’ları tanımlarken ( ve ) içindeki { ve } süslü parantez çiftini unutmayın:

function Avatar({ person, size }) {
// ...
}

Bu sözdizimi “yapı çözme” olarak adlandırılır ve bir fonksiyon parametresinden prop’ları okumaya eşdeğerdir:

function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}

Bir prop için varsayılan değeri belirleme

Bir prop’a, belirtilen değer olmadığında geri dönecek varsayılan bir değer vermek isterseniz, parametreden hemen sonra = ve varsayılan değeri koyarak yapı çözmeyle yapabilirsiniz:

function Avatar({ person, size = 100 }) {
// ...
}

Şimdi, <Avatar person={...} /> size prop’u belirtilmeden render edilirse, size 100 olarak ayarlanacaktır.

Varsayılan değer yalnızca, size prop’u eksikse veya size={undefined} olarak geçirilirse kullanılır. Ancak size={null} veya size={0} olarak geçirirseniz, varsayılan değer kullanılmaz.

JSX yayılım sözdizimiyle prop’ları iletmek

Bazı durumlarda, prop’ları aktarmak çok tekrar edici olabilir:

function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}

Tekrarlayan kodda yanlış olan bir şey yoktur. Daha okunaklı olabilir. Ancak bazen kısa ve öz olmaya önem verirsiniz. Bazı bileşenler, bu Profile bileşeninin Avatar ile yaptığı gibi, tüm prop’larını alt elemanlarına iletirler. Doğrudan hiçbir prop kullanmadıklarından, daha özlü “yayılma (spread)” sözdizimi kullanmak mantıklı olabilir:

function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}

Bu, her birinin adını listeleyerek Profile’ın tüm prop’larını Avatar’a iletiyor.

Spread sözdizimini ölçülü bir şekilde kullanın. Her diğer bileşende bunu kullanıyorsanız, bir şeyler yanlış demektir. Çoğu zaman, bileşenlerinizi ayırmanız ve alt elemanları JSX olarak iletilmesi gerektiği anlamına gelir. Sonraki adımda daha fazlası var!

JSX’i alt eleman olarak aktarma

Dahili tarayıcı etiketlerini iç içe geçirmek yaygındır:

<div>
<img />
</div>

Bazen kendi bileşenlerinizi aynı şekilde iç içe yerleştirmek istersiniz:

<Card>
<Avatar />
</Card>

Bir JSX etiketi içine içerik yerleştirdiğinizde, üst eleman, children adında bir prop’un içinde bu içeriği alacaktır. Örneğin, aşağıdaki Card bileşeni, <Avatar /> olarak ayarlanmış bir children prop’u alacak ve bunu bir sarma divinde render edilecektir:

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>
  );
}

<Card> içindeki <Avatar>’ı bir metinle değiştirerek, Card bileşeninin herhangi bir iç içe içeriği sarmalayabileceğini görmek için deneyebilirsiniz. İçinde neyin render edildiğini “bilmesi” gerekmez. Bu esnek kalıbı birçok yerde göreceksiniz.

Bir children prop’una sahip bir bileşeni, üst elemanların istediği JSX ile “doldurabileceği” bir “delik” olarak düşünebilirsiniz. Sıklıkla, görsel sarmalayıcılar için (panel, grid vb.) children prop’u kullanacaksınız.

Metin ve Avatar gibi "alt" parçaları için bir yer olan, bir bulmaca kartı benzeri bir Card örneği

Rachel Lee Nabors tarafından görselleştirilmiştir.

Aşağıdaki Clock bileşeni, üst elemandan iki prop alır: color ve time. (Üst elemanın kodu, henüz incelemeyeceğimiz durum (state) kullandığı için atlanmıştır.)

Aşağıdaki seçim kutusunda rengi değiştirmeyi deneyin:

export default function Clock({ color, time }) {
  return (
    <h1 style={{ color: color }}>
      {time}
    </h1>
  );
}

Bu örnek, bir bileşenin zamanla farklı prop’lar alabileceğini gösterir. Prop’lar her zaman statik değildir! Burada time prop’u her saniyede bir değişir ve color prop’u başka bir renk seçtiğinizde değişir. Prop’lar, bir bileşenin verilerini sadece başlangıçta değil, herhangi bir zamandaki durumunu yansıtır.

Ancak, prop’lar immutable (değiştirilemez) özelliktedir - bilgisayar bilimlerinde “değiştirilemez” anlamına gelen bir terimdir. Bir bileşen, prop’larını değiştirmesi gerektiğinde (örneğin, bir kullanıcı etkileşimine veya yeni verilere yanıt olarak), farklı bir nesne olan farklı prop’ları geçmesi için üst elemanından “istemek” zorunda kalacaktır! Eski prop’ları atılacak ve sonunda JavaScript motoru tarafından bunların işgal ettiği bellek geri alınacaktır.

Prop’ları “değiştirmeye” çalışmayın. Kullanıcı girdisine yanıt vermeniz gerektiğinde (seçilen rengi değiştirme gibi), State: Bir Bileşenin Belleği konusunda öğrenebileceğiniz şekilde “state ayarı” yapmanız gerekecektir.

Özet

  • Prop’ları geçmek için, HTML özniteliklerini geçirdiğiniz gibi JSX’e ekleyin.
  • Prop’ları okumak için, function Avatar({ person, size }) yapısını kullanın.
  • Eksik veya tanımlanmamış prop’lar için kullanılan size = 100 gibi varsayılan bir değer belirleyebilirsiniz.
  • Tüm prop’ları <Avatar {...props} /> JSX spread sözdizimi ile iletebilirsiniz, ancak bunu abartmayın!
  • <Card><Avatar /></Card> gibi iç içe JSX, Card bileşeninin children prop’u olarak görüntülenecektir.
  • Prop’lar, her render işlemi bir prop’ların yeni bir sürümünü aldığı için okunur ve değiştirilemez.
  • Prop’ları değiştiremezsiniz. Etkileşimli bir bileşen için, state ayarlaması yapmanız gerekecektir.

Problem 1 / 3:
Bileşen Ayıklama

Bu Gallery bileşeni, iki profille ilgili çok benzer bir işaretleme içerir. Yinelemeyi azaltmak için bunun dışında bir Profile bileşeni çıkarın. Hangi prop’ların geçirileceğine karar vermeniz gerekecektir.

import { getImageUrl } from './utils.js';

export default function Gallery() {
  return (
    <div>
      <h1>Önemli Bilim İnsanları</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>Meslek: </b> 
            fizikçi ve kimyager
          </li>
          <li>
            <b>Ödüller: 4 </b> 
            (Fizik Nobel Ödülü, Kimya Nobel Ödülü, Davy Madalyası, Matteucci Madalyası)
          </li>
          <li>
            <b>Keşfedilenler: </b>
            polonyum (kimyasal 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>Meslek: </b> 
            jeokimyager
          </li>
          <li>
            <b>Ödüller: 2 </b> 
            (Miyake Ödülü (jeokimya), Tanaka Ödülü)
          </li>
          <li>
            <b>Keşfedilenler: </b>
            deniz suyundaki karbondioksit ölçüm yöntemi
          </li>
        </ul>
      </section>
    </div>
  );
}