Derinlemesine JSX

Temel olarak, JSX sadece React.createElement(component, props, ...children) fonksiyonları için syntax sağlar.

JSX kodu:

<MyButton color="blue" shadowSize={2}>
  Tıkla
</MyButton>

Yukarıdaki kodu, bu koda derler:

React.createElement(
  MyButton,
  {color: 'blue', shadowSize: 2},
  'Tıkla'
)

Hiçbir child yoksa etiketi direkt kapatarakta kullanabilirsiniz:

<div className="sidebar" />

Yukarıdaki kodu, bu koda derler:

React.createElement(
  'div',
  {className: 'sidebar'},
  null
)

JSX’in JavaScript’e nasıl dönüştürüldüğünü test etmek isterseniz, online Babel derleyicisini deneyebilirsiniz.

React'te Element Tipini Belirleme

Bir JSX etiketinin ilk harfi, React elementinin türünü belirler.

Büyük harfle başlayan bir JSX etiketi, bunun bir React componenti olduğunu belirtir. Bu etiketler, adlandırılmış değişkene doğrudan referans olarak derlenir; bu nedenle, JSX <Foo /> ifadesini kullanırsanız, Foo scope (kapsam) dahilinde olmalıdır.

React Scope'ta Olmalı

JSX React.createElement çağrısına derlediğinden, React kitaplığı daima JSX kodunuzun scope’unda olmalıdır.

Örneğin, React ve CustomButton doğrudan JavaScript’te atıf yapılmamasına rağmen, bu kodda her iki importta gereklidir:

import React from 'react';
import CustomButton from './CustomButton';

function WarningButton() {
  // return React.createElement(CustomButton, {color: 'red'}, null);
  return <CustomButton color="red" />;
}

Bir JavaScript paketleyicisi kullanmazsanız ve React’i <script> etiketi ile yüklediyseniz, zaten React globali scopetadır.

Nokta Notasyonunu JSX Türü İçin Kullanma

JSX içinde nokta işareti kullanarak bir React componentine başvurabilirsiniz. Birçok React componenti ihraç eden bir modülünüz varsa bu uygundur. Örneğin, MyComponents.DatePicker bir component ise, bunu doğrudan JSX’den şu şekilde kullanabilirsiniz:

import React from 'react';

const MyComponents = {
  DatePicker: function DatePicker(props) {  
    return <div>Buraya {props.color} geldiğini düşünün.</div>;
  }
}

function BlueDatePicker() {
  return <MyComponents.DatePicker color="blue" />;
}

Componentler Büyük Harf İle Başlamalıdır

Bir element türü küçük harfle başlarsa, <div> veya <span> gibi yerleşik bir componente atıfta bulunur ve React.createElement alanına aktarılan bir string 'div' veya 'span' ile sonuçlanır. <Foo /> gibi büyük harfle başlayan türler React.createElement(Foo)‘ya derlenir ve JavaScript dosyanızda tanımlanmış veya içe aktarılmış bir componente karşılık gelir.

Componentlerin ilk harfini büyük harfle isimlendirmenizi öneririz. Küçük harfle başlayan bir componente sahipseniz, JSX’de kullanmadan önce baş harfini büyük harfe dönüştürün.

Örneğin, bu kod beklendiği gibi çalışmaz:

import React from 'react';

// Hata! Bu bir component ve baş harfi büyük yazılmış olmalıydı:
function hello(props) {
  // Doğru! Div, geçerli bir HTML etiketi olduğu için <div> kullanımının meşru olduğunu söyleyebiliriz.
  return <div>Merhaba {props.toWhat}</div>;
}

function HelloWorld() {
  // Yanlış! React <hello />'nun büyük harf kullanmadığından bunun bir HTML etiketi olduğunu düşünür.
  return <hello toWhat="World" />;
}

Bunu düzeltmek için, hello elementini Hello olarak yeniden adlandırıp, ona atıfta bulunmak için ise <Hello /> kullanacağız:

import React from 'react';

// Doğru! Bu bir component ve baş harfi büyük yazılmıştır:
function Hello(props) {
  // Doğru! Div, geçerli bir HTML etiketi olduğu için <div> kullanımının meşru olduğunu söyleyebiliriz.
  return <div>Merhaba {props.toWhat}</div>;
}

function HelloWorld() {
  // Doğru! React, <Hello />'nun component olduğunu bilir çünkü büyük harfle başlamıştır.
  return <Hello toWhat="World" />;
}

Runtime Olarak Tür Seçimi

React element türü olarak genel bir ifade kullanamazsınız. Elementin türünü belirtmek için genel bir ifade kullanmak istiyorsanız, önce önce baş harfi büyük bir değişkene atayın. Bu, genellikle bir pakete dayalı farklı bir component oluşturmak istediğinizde ortaya çıkar:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // Yanlış! JSX türü bir obje olamaz.
  return <components[props.storyType] story={props.story} />;
}

Bunu düzeltmek için önce türü baş harfi büyük bir değişkene atayacağız:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // Doğru! JSX türü baş harfi büyük yazılmış bir değişken olabilir.
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

JSX'te Propslar

Propsları JSX’de belirtmenin birkaç farklı yolu vardır.

JavaScript İfadeleri Olarak Props

Herhangi bir JavaScript ifadesini {} ile çevreleyerek yazabilirsiniz. Örneğin, bu JSX’de:

<MyComponent foo={1 + 2 + 3 + 4} />

MyComponent için, props.foo değeri 1 + 2 + 3 + 4 ifadesini hesaplar ve 10 olur.

if ifadelerini ve for döngülerini JSX’te doğrudan kullanamayız. Bunun yerine, bunları çevreleyen koda yerleştirebilirsiniz.

Örneğin:

function NumberDescriber(props) {
  let description;
  if (props.number % 2 == 0) {
    description = <strong>even</strong>;
  } else {
    description = <i>odd</i>;
  }
  return <div>{props.number}, {description} sayıdır.</div>;
}

Şartlı render ve döngüler hakkında ilgili bölümlerde daha fazla bilgi edinebilirsiniz.

String Literaller

Bir string ifadeyi props olarak geçirebilirsiniz. Bu iki JSX ifadesi aynıdır:

<MyComponent message="Merhaba Dünya" />

<MyComponent message={'Merhaba Dünya'} />

Bir string gönderirken, değeri HTML-unescaped’dir. Dolayısıyla bu iki JSX ifadesi aynıdır:

<MyComponent message="&lt;3" />

<MyComponent message={'<3'} />

Propslar Default Olarak True'dur

Değer girmezseniz, default (varsayılan) olarak propslar true olur. Bu iki JSX ifadesi aynıdır.

<MyTextBox autocomplete />

<MyTextBox autocomplete={true} />

Genel olarak bunu kullanmanızı önermiyoruz çünkü {foo: true} yerine, {foo: foo} için kısa olan ES6 nesne kısayolu {foo} ile karıştırılabilir.

Spread Attributeler

Bir propsunuz varsa ve bunu JSX’de geçirmek istiyorsanız, bütün props nesnesini geçmek için ...yı spread bir operatör olarak kullanabilirsiniz. Bu iki component aynıdır:

function App1() {
  return <Greeting firstName="Ömer" lastName="Gülçiçek" />;
}

function App2() {
  const props = {firstName: 'Ömer', lastName: 'Gülçiçek'};
  return <Greeting {...props} />;
}

Ayrıca, tüm propsları geçirirken componentinizin tüketeceği belirli propsu ayrı olarak seçebilirsiniz.

const Button = props => {
  const { kind, ...other } = props;
  const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
  return <button className={className} {...other} />;
};

const App = () => {
  return (
    <div>
      <Button kind="primary" onClick={() => console.log("Tıklandı!")}>
        Merhaba Dünya!
      </Button>
    </div>
  );
};

Yukarıdaki örnekte kind güvenli bir şekilde tüketilir ve DOM’da <button> elemanına geçirilmez. Diğer tüm propslar, ...other nesnesi aracılığıyla geçirilir ve bu component gerçekten esnek hale gelir. Bir onClick ve children propsundan geçtiğini görebilirsiniz.

Spread attributeleri kullanışlı olabilir, ancak gereksiz componentleri kendileri için önemsemeyen componentlere veya geçersiz HTML attributelerini DOM’a geçirmeyi kolaylaştırır. Bu syntaxı dikkatli kullanmanızı öneririz.

JSX'te Children

Hem bir açılış etiketi hem de bir kapanış etiketi içeren JSX ifadelerde, bu etiketler arasındaki içerik props.children olarak aktarılır. Childrenları geçmenin birkaç farklı yolu vardır:

Bu konu ile ilgili olan composition ve inheritance konusunuda okuyabilirsiniz.

String Literaller

Açılış ve kapanış etiketleri arasına bir string koyabiliriz, bu string props.children olacaktır. Örneğin:

<MyComponent>Merhaba Dünya!</MyComponent>

Bu geçerli JSX’dir ve MyComponentdeki props.children, basitçe “Merhaba Dünya!” stringi olacaktır.

JSX bir satırın başında ve sonunda olan boşlukları kaldırır. Boş satırları da kaldırır. Etiketlerin yanındaki yeni satırlar kaldırılır; string değişkenlerinin ortasında oluşan yeni satırlar tek bir alana yoğuşturulur. Yani aşağıdaki örneklerin hepsi aynı şeyi yapar:

<div>Merhaba Dünya/div>

<div>
  Merhaba Dünya
</div>

<div>
  Merhaba
  Dünya
</div>

<div>

  Merhaba Dünya
</div>

JSX'te Children

İstediğiniz kadar componenti children (çocuk) olarak kullanabilirsiniz, iç içe geçmiş componentleri görüntülemek için kullanışlıdır:

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

Bir React componenti dizi return edebilir:

render() {
  // Liste öğelerini fazladan bir element ile sarmanıza gerek yok!
  return [
    // Keyleri unutmayın
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

Keyler hakkında detaylı bilgi için listeler ve keyler konusundan keyler başlığına bakabilirsiniz.

Children JavaScript İfadeleri

JavaScript ifadesini childrena {}e koyarak geçirebilirsiniz. Örneğin, bu ifadeler aynıdır:

<MyComponent>Örnek</MyComponent>

<MyComponent>{'Örnek'}</MyComponent>

Bu, keyfi uzunlukta JSX ifadelerinin bir listesini oluşturmak için genellikle yararlıdır. Örneğin, bu bir HTML listesi oluşturur:

function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['Ömer', 'Burak', 'Muhammed'];
  return (
    <ul>
      {todos.map((message) => <Item key={message} message={message} />)}
    </ul>
  );
}

JavaScript ifadeleri diğer children türleri ile birlikte kullanılabilir. Bu genellikle string şablonlarının yerine yararlıdır:

function Hello(props) {
  return <div>Merhaba {props.addressee}!</div>;
}

Children Türünden Functions

Normalde, JSX’e eklenen JavaScript ifadeleri bir stringe, bir React elementi veya bu şeylerin bir listesine göre değerlendirilir. Bununla birlikte, props.children, yalnızca React’in nasıl yapılacağını bildiği türden değil, herhangi bir veri türünden geçebileceği için diğer herhangi bir props gibi çalışır. Örneğin, özel bir componente sahipseniz, bir callback’i props.children olarak almasını sağlayabilirsiniz:

// Tekrarlanan bir component üretmek için childrenların callback'leri çağırır
function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>Bu listede {index} olan öğedir.</div>}
    </Repeat>
  );
}

Booleans, Null ve Undefined Yok Sayılır

false, null, undefined ve true geçerli childrenlardır. Onlar sadece render yapılmazlar. Bu JSX ifadeleri hep aynı şeyi yapacak:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

Bu, koşullu olarak React elementlerini oluşturmak için yararlı olabilir. JSX yalnızca showHeader true ise <Header /> componentini görür, false ise görmez:

<div>
  {showHeader && <Header />}
  <Content />
</div>

Bir uyarı, ‘0’ sayısı gibi bazı falsy değerleri React tarafından render edilir. Örneğin, bu kod, props.messages boş bir dizi olduğunda ‘0’ yazdırılacağı için beklediğiniz gibi davranmayacaktır:

<div>
  {props.messages.length &&
    <MessageList messages={props.messages} />
  }
</div>

Falsy değeri, boolean bağlamında değerlendirildiğinde false değerine çeviren bir değerdir. JavaScript, if-else ve döngüler gibi herhangi bir değeri bir boolena gerektiren bağlamlarda zorlamak için tür tipi dönüştürme özelliğini kullanır.

JavaScript’teki false değerlerin örnekleri (false’a çevrilir ve böylece if bloğunu atlar):

if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (document.all) [1]

Normalde true && kod olduğunda ilk ifade true olduğu için sağ kısımdaki kod çalışacaktır. false && kod olduğunda ise kod hiçbir çıktı vermeyecektir. JavaScript’te 1 && kod olduğunda 1’i true olarak değerlendirip kodu çalıştırır fakat 0 && kod olduğunda 0’ı false olarak değerlendirmez ve ekrana 0 yazar.

Bunu düzeltmek için, && önündeki ifadenin her zaman boolean olduğundan emin olun:

<div>
  {props.messages.length > 0 &&
    <MessageList messages={props.messages} />
  }
</div>

Aksine, çıktıda false, true, null veya undefined gibi bir değerleri görmek istiyorsanız, önce bir string haline getirmeniz gerekir:

<div>
  JavaScript değişkenim {String(myVariable)}.
</div>

Sıradaki Gelişmiş Kılavuz: ES6 Olmadan React