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="<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 props
unuz 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 MyComponent
deki 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>