Skip to main content

JSX Temelleri: JavaScript'te HTML Yazmak

JSX, React'in gücünü ortaya çıkaran sözdizimi uzantısıdır. Bu derste JSX'i derinlemesine öğrenecek, gerçek dünya örnekleriyle pratik yapacaksınız.

JSX Nedir?
JSX (JavaScript XML), JavaScript içinde HTML benzeri kod yazmanıza olanak tanıyan bir sözdizimi uzantısıdır. React uygulamalarında UI bileşenleri oluşturmayı sezgisel ve okunabilir hale getirir. JSX opsiyoneldir ancak React ekosisteminde standart haline gelmiştir.

1. JSX Nedir ve Neden Kullanılır?

JSX, JavaScript'in bir uzantısıdır ve HTML'e çok benzer bir sözdizimi sağlar. Ancak aslında JavaScript'tir ve kodunuz çalıştığında React.createElement() çağrılarına dönüştürülür.

Greeting.tsx
1function Greeting() {
2 return <h1 className="title">Merhaba, Dünya!</h1>;
3}

Temiz, okunabilir ve HTML'e çok benzer.

JSX Neden Daha İyi?
JSX kullanmak zorunda değilsiniz, ancak React.createElement() yazmaktan çok daha hızlı ve okunabilirdir. Özellikle karmaşık bileşenlerde fark büyük olur.

2. JSX Sözdizimi Kuralları

JSX HTML'e benzer, ancak bazı önemli farklılıkları vardır. Bu kuralları bilmek hata yapmaktan kaçınmanızı sağlar.

Temel JSX Kuralları

Tek Üst Element
JSX ifadelerinin tek bir kök (root) elementi olmalıdır. Birden fazla element döndürmek için Fragment kullanın veya bir div ile sarmalayın.
Tüm Etiketler Kapalı
HTML'de bazı etiketler (img, br, input) kapanış etiketi gerektirmez. JSX'te MUTLAKA kapatılmalı veya self-closing olmalıdır (örn: <img />, <br />).
className Kullanın
HTML'de class kullanırken, JSX'te className kullanmalısınız çünkü class JavaScript'te reserved keyword'dür.
camelCase Attribute'ler
HTML attribute'leri (onclick, tabindex) JSX'te camelCase olmalıdır (onClick, tabIndex). Tek istisna: data-* ve aria-* attribute'leri kebab-case kalır.
Inline Style = Obje
HTML'de style bir string'dir. JSX'te style bir JavaScript objesidir ve CSS property'leri camelCase yazılır.
JavaScript İfadeleri
JSX içinde JavaScript ifadeleri süslü parantez içine yazılır. Bu içinde değişken, fonksiyon çağrısı, ternary operator vs. kullanabilirsiniz.

HTML vs JSX: Kritik Farklar

HTMLJSX
Class tanımlamaclass="btn primary"className="btn primary"
Event handleronclick="handleClick()"onClick={handleClick}
Style attributestyle="color: red; font-size: 16px"style={{ color: "red", fontSize: 16 }}
Self-closing tags<img src="..."> veya <img src="..." /><img src="..." /> (zorunlu)
For attribute (label)<label for="username"><label htmlFor="username">
Boolean attributes<input disabled><input disabled={true} />
Comments<!-- HTML yorum -->{/* JSX yorum */}
Yaygın Hata: Çoklu Kök Element
tsx
1// ❌ YANLIŞ - Çoklu kök element
2function MyComponent() {
3 return (
4 <h1>Başlık</h1>
5 <p>Paragraf</p>
6 );
7}
8
9// ✅ DOĞRU - Fragment kullanımı
10function MyComponent() {
11 return (
12 <>
13 <h1>Başlık</h1>
14 <p>Paragraf</p>
15 </>
16 );
17}
18
19// ✅ DOĞRU - Sarmalayıcı div
20function MyComponent() {
21 return (
22 <div>
23 <h1>Başlık</h1>
24 <p>Paragraf</p>
25 </div>
26 );
27}

3. JSX İçinde JavaScript İfadeleri

JSX'in en güçlü özelliği, JavaScript ifadelerini doğrudan markup içinde kullanabilmenizdir. Süslü parantez içinde neredeyse her JavaScript ifadesi çalışır.

3.1 Değişkenleri Kullanma

UserCard.tsx
1function UserCard() {
2 const name = 'Ayşe Yılmaz';
3 const age = 28;
4 const profilePic = '/images/ayse.jpg';
5
6 return (
7 <div className="user-card">
8 <img src={profilePic} alt={`${name} profil fotoğrafı`} />
9 <h2>{name}</h2>
10 <p>Yaş: {age}</p>
11 </div>
12 );
13}

3.2 İfadeler ve Hesaplamalar

ShoppingCart.tsx
1function ShoppingCart() {
2 const items = [
3 { name: 'Laptop', price: 15000, qty: 1 },
4 { name: 'Mouse', price: 200, qty: 2 },
5 ];
6
7 const total = items.reduce(
8 (sum, item) => sum + item.price * item.qty, 0
9 );
10
11 return (
12 <div>
13 <h2>Sepet ({items.length} ürün)</h2>
14 <p>Toplam: {total} TL</p>
15 <p>KDV Dahil: {(total * 1.18).toFixed(2)} TL</p>
16 </div>
17 );
18}
İfade vs İfade Cümlesi

Süslü parantez içinde sadece ifadeler (expressions) kullanılabilir:

  • ✅ Değişkenler: {name}
  • ✅ Aritmetik: {2 + 2}
  • ✅ Fonksiyon çağrısı: {getName()}
  • ✅ Ternary: {isActive ? 'Aktif' : 'Pasif'}
  • ❌ if/else: {if (x) ... } (çalışmaz!)
  • ❌ for loop: {for ... } (çalışmaz!)

3.3 Fonksiyon Çağrıları

DateDisplay.tsx
1function DateDisplay() {
2 function formatDate(date: Date): string {
3 return date.toLocaleDateString('tr-TR', {
4 weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
5 });
6 }
7
8 return (
9 <div>
10 <p>Bugün: {formatDate(new Date())}</p>
11 <p>Tarih formatı: {new Date().toISOString()}</p>
12 <p>Unix timestamp: {Date.now()}</p>
13 </div>
14 );
15}

4. Koşullu Rendering (Conditional Rendering)

React'te koşula göre farklı UI render etmek çok yaygındır. JSX içinde if/else kullanamayacağınız için JavaScript'in koşullu ifadelerini kullanırsınız.

4.1 Ternary Operator (? :)

LoginButton.tsx
1function LoginButton({ isLoggedIn }: { isLoggedIn: boolean }) {
2 return (
3 <div>
4 {isLoggedIn ? (
5 <button>Çıkış Yap</button>
6 ) : (
7 <button>Giriş Yap</button>
8 )}
9 </div>
10 );
11}

4.2 Logical AND (&&)

Bir koşul true ise element göster, false ise hiçbir şey gösterme senaryoları için ideal.

Notification.tsx
1function Notification({ hasNotifications, count }: { hasNotifications: boolean; count: number }) {
2 return (
3 <div>
4 <h2>Bildirimler</h2>
5 {hasNotifications && (
6 <span className="badge">{count} yeni bildirim</span>
7 )}
8 </div>
9 );
10}
Dikkat: Falsy Değerler

&& operatörü ile 0 veya "" kullanırken dikkatli olun:

tsx
1// ❌ SORUN - count=0 olduğunda "0" yazısı görünür
2{count && <span>{count} ürün</span>}
3
4// ✅ ÇÖZÜM - Boolean dönüşümü yapın
5{count > 0 && <span>{count} ürün</span>}
6{Boolean(count) && <span>{count} ürün</span>}

4.3 Değişkene Atama Yöntemi

WelcomeMessage.tsx
1function WelcomeMessage({ role }: { role: 'admin' | 'user' | 'guest' }) {
2 let message;
3
4 if (role === 'admin') {
5 message = <h1>Admin Paneline Hoş Geldiniz</h1>;
6 } else if (role === 'user') {
7 message = <h1>Kullanıcı Sayfasına Hoş Geldiniz</h1>;
8 } else {
9 message = <h1>Misafir olarak giriş yaptınız</h1>;
10 }
11
12 return (
13 <div>{message}</div>
14 );
15}

4.4 Switch/Case Alternatifi: Object Mapping

StatusBadge.tsx
1function StatusBadge({ status }: { status: 'success' | 'error' | 'warning' | 'info' }) {
2 const statusConfig = {
3 success: { text: 'Başarılı', color: 'green' },
4 error: { text: 'Hata', color: 'red' },
5 warning: { text: 'Uyarı', color: 'yellow' },
6 info: { text: 'Bilgi', color: 'blue' }
7 };
8
9 const config = statusConfig[status];
10
11 return (
12 <span className={`badge bg-${config.color}`}>
13 {config.text}
14 </span>
15 );
16}

5. Listeleri Render Etme ve Key Prop

Dinamik veri listelerini render etmek React'te çok yaygındır. JavaScript'inmap() fonksiyonu bu iş için mükemmeldir.

5.1 Basit Liste

FruitList.tsx
1function FruitList() {
2 const fruits = ['Elma', 'Muz', 'Portakal', 'Çilek', 'Karpuz'];
3
4 return (
5 <ul>
6 {fruits.map((fruit, index) => (
7 <li key={index}>{fruit}</li>
8 ))}
9 </ul>
10 );
11}

5.2 Obje Listesi

ProductList.tsx
1interface Product {
2 id: string;
3 name: string;
4 price: number;
5}
6
7function ProductList({ products }: { products: Product[] }) {
8 return (
9 <div className="grid gap-4">
10 {products.map((product) => (
11 <div key={product.id} className="card">
12 <h3>{product.name}</h3>
13 <p className="price">{product.price} TL</p>
14 <button>Sepete Ekle</button>
15 </div>
16 ))}
17 </div>
18 );
19}
Key Prop: Kritik Önem!

Liste render ederken her zaman benzersiz bir key prop kullanmalısınız:

  • İyi: Benzersiz ID kullanın (key={item.id})
  • ⚠️ Kabul Edilebilir: Index kullanın, ancak sadece liste statikse ve yeniden sıralanmıyorsa
  • Kötü: Key kullanmamak (React uyarısı verir)
  • Kötü: Her render'da değişen bir değer (Math.random() gibi)

Neden önemli? React, key'leri kullanarak hangi öğelerin değiştiğini, eklendiğini veya silindiğini anlar. Yanlış key kullanımı performans sorunlarına ve hatalı render'lara neden olabilir.

5.3 Filtreleme ve Koşullu Liste

TaskList.tsx
1interface Task {
2 id: string;
3 title: string;
4 completed: boolean;
5}
6
7function TaskList({ tasks }: { tasks: Task[] }) {
8 // Sadece tamamlanmamış görevleri filtrele
9 const pendingTasks = tasks.filter(task => !task.completed);
10
11 // Boş liste kontrolü
12 if (pendingTasks.length === 0) {
13 return <p>Tüm görevler tamamlandı! 🎉</p>;
14 }
15
16 return (
17 <ul>
18 {pendingTasks.map(task => (
19 <li key={task.id}>{task.title}</li>
20 ))}
21 </ul>
22 );
23}

6. React Fragments: Gereksiz div'lerden Kurtulun

JSX'te birden fazla element döndürmek için bir parent element gerekir. Ancak bazen gereksiz div wrapper'ları DOM'u karmaşıklaştırır. Fragment bu sorunu çözer.

Fragment Kullanımı

Uzun SyntaxKısa Syntax
Syntax<React.Fragment>...</React.Fragment><>...</>
AvantajKey prop alabilirKısa ve temiz
DezavantajDaha uzun kodKey prop alamaz
Kullanım senaryosuListe içinde fragment kullanımıGenel kullanım
Table.tsx
1function TableRows() {
2 const data = [
3 { id: 1, name: 'Ahmet', age: 25 },
4 { id: 2, name: 'Mehmet', age: 30 }
5 ];
6
7 return (
8 <>
9 {data.map(person => (
10 // Fragment ile key kullanımı
11 <React.Fragment key={person.id}>
12 <tr>
13 <td>{person.name}</td>
14 <td>{person.age}</td>
15 </tr>
16 <tr>
17 <td colSpan={2}>Detay bilgiler...</td>
18 </tr>
19 </React.Fragment>
20 ))}
21 </>
22 );
23}

7. Olay Yönetimi (Event Handling)

JSX'te event handler'lar camelCase yazılır ve fonksiyon referansı olarak verilir (string olarak değil).

7.1 Temel Event Handler

Button.tsx
1function ClickButton() {
2 function handleClick() {
3 alert('Butona tıklandı!');
4 }
5
6 return (
7 <button onClick={handleClick}>Tıkla</button>
8 );
9}
Yaygın Hata: Fonksiyonu Çağırmak
tsx
1// ❌ YANLIŞ - Fonksiyon hemen çalışır
2<button onClick={handleClick()}>Tıkla</button>
3
4// ✅ DOĞRU - Fonksiyon referansı verilir
5<button onClick={handleClick}>Tıkla</button>
6
7// ✅ DOĞRU - Arrow function ile sarmalama (parametre gerekiyorsa)
8<button onClick={() => handleClick('parametre')}>Tıkla</button>

7.2 Event Objesini Kullanma

Form.tsx
1function SearchInput() {
2 function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
3 const value = event.target.value;
4 console.log('Arama:', value);
5 }
6
7 return (
8 <input type="text" onChange={handleChange} placeholder="Ara..." />
9 );
10}

7.3 Form Submission

LoginForm.tsx
1function LoginForm() {
2 function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
3 event.preventDefault(); // Sayfa yenilenmesini engelle
4
5 const formData = new FormData(event.currentTarget);
6 const email = formData.get('email');
7 console.log('Giriş:', email);
8 }
9
10 return (
11 <form onSubmit={handleSubmit}>
12 <input name="email" type="email" required />
13 <input name="password" type="password" required />
14 <button type="submit">Giriş Yap</button>
15 </form>
16 );
17}

8. Props ve Children Pattern

8.1 Props ile Veri Aktarımı

UserProfile.tsx
1interface UserProfileProps {
2 name: string;
3 age: number;
4 avatar?: string; // Opsiyonel
5}
6
7function UserProfile({ name, age, avatar = '/default-avatar.png' }: UserProfileProps) {
8 return (
9 <div className="profile">
10 <img src={avatar} alt={name} />
11 <h2>{name}</h2>
12 <p>{age} yaşında</p>
13 </div>
14 );
15}
16
17// Kullanım
18<UserProfile name="Ayşe" age={25} />
19<UserProfile name="Mehmet" age={30} avatar="/mehmet.jpg" />

8.2 Children Prop

Card.tsx
1interface CardProps {
2 title: string;
3 children: React.ReactNode;
4}
5
6function Card({ title, children }: CardProps) {
7 return (
8 <div className="card">
9 <h3>{title}</h3>
10 <div className="card-body">{children}</div>
11 </div>
12 );
13}
14
15// Kullanım
16<Card title="Kullanıcı Bilgileri">
17 <p>Ayşe Yılmaz</p>
18 <p>Frontend Developer</p>
19 <button>Profil</button>
20</Card>

8.3 Spread Props

Input.tsx
1function Input(props: React.InputHTMLAttributes<HTMLInputElement>) {
2 return (
3 <input
4 className="custom-input"
5 {...props}
6 />
7 );
8}
9
10// Kullanım - tüm HTML input attribute'lerini destekler
11<Input type="email" placeholder="E-posta" required />
12<Input type="password" minLength={8} />

9. JSX'te Styling

9.1 Inline Styles

StyledComponent.tsx
1function StyledBox() {
2 const boxStyle = {
3 backgroundColor: '#3b82f6',
4 color: 'white',
5 padding: '1rem',
6 borderRadius: '0.5rem'
7 };
8
9 return (
10 <div style={boxStyle}>
11 Styled Box
12 </div>
13 );
14}
Inline Style Kuralları
  • CSS property'leri camelCase yazılır: backgroundColor, fontSize
  • Değerler string veya number: {{ width: '100px' }} veya {{ width: 100 }}
  • Number değerler otomatik px olur (width, height vs.): {{ width: 100 }} → "100px"
  • Çift süslü parantez: style={{ ... }} (dış JSX ifadesi, iç JavaScript objesi)

9.2 className ile CSS

Button.tsx
1function Button({ variant = 'primary' }: { variant?: 'primary' | 'secondary' }) {
2 const baseClass = 'btn';
3 const variantClass = variant === 'primary' ? 'btn-primary' : 'btn-secondary';
4
5 return (
6 <button className={`${baseClass} ${variantClass}`}>
7 Tıkla
8 </button>
9 );
10}

9.3 Conditional Classes (cn helper)

Alert.tsx
1import { cn } from '@/lib/utils'; // Tailwind + clsx helper
2
3function Alert({ type, children }: { type: 'info' | 'error'; children: React.ReactNode }) {
4 return (
5 <div
6 className={cn(
7 'p-4 rounded-lg', // Base classes
8 type === 'info' && 'bg-blue-100 text-blue-900',
9 type === 'error' && 'bg-red-100 text-red-900'
10 )}
11 >
12 {children}
13 </div>
14 );
15}

10. JSX Best Practices

JSX Yazımında En İyi Pratikler

1

Bileşenleri Küçük Tutun

Her bileşen tek bir şey yapmalı. Çok büyük bileşenleri daha küçük, yeniden kullanılabilir parçalara bölün.

tsx
1// ✅ İyi
2function ProductCard({ product }) {
3 return (
4 <div>
5 <ProductImage src={product.image} />
6 <ProductInfo name={product.name} price={product.price} />
7 <AddToCartButton productId={product.id} />
8 </div>
9 );
10}
2

Prop Destructuring Kullanın

Props'u destructure ederek daha temiz kod yazın.

tsx
1// ❌ Kötü
2function User(props) {
3 return <h1>{props.name}</h1>;
4}
5
6// ✅ İyi
7function User({ name }) {
8 return <h1>{name}</h1>;
9}
3

Key Prop'u Doğru Kullanın

Liste render ederken her zaman benzersiz, stabil key kullanın.

tsx
1// ❌ Kötü - index
2{items.map((item, i) => <div key={i}>...</div>)}
3
4// ❌ Kötü - random
5{items.map(item => <div key={Math.random()}>...</div>)}
6
7// ✅ İyi - benzersiz ID
8{items.map(item => <div key={item.id}>...</div>)}
4

Event Handler İsimlendirme

Event handler'ları handle ile başlatın.

tsx
1function Form() {
2 const handleSubmit = () => { ... };
3 const handleChange = () => { ... };
4 const handleCancel = () => { ... };
5
6 return <form onSubmit={handleSubmit}>...</form>;
7}
5

Koşulları Erken Return ile Basitleştirin

Karmaşık koşullu rendering yerine early return kullanın.

tsx
1function UserList({ users }) {
2 // Early return ile boş durum kontrolü
3 if (!users || users.length === 0) {
4 return <p>Kullanıcı bulunamadı</p>;
5 }
6
7 return (
8 <ul>
9 {users.map(user => <li key={user.id}>{user.name}</li>)}
10 </ul>
11 );
12}

11. Yaygın JSX Hataları ve Çözümleri

12. Özet ve Sırada Ne Var?

Tebrikler! JSX'te Uzmanlaştınız

Bu derste şunları öğrendiniz:

  • ✅ JSX'in ne olduğu ve JavaScript'e nasıl dönüştüğü
  • ✅ JSX sözdizimi kuralları ve HTML'den farkları
  • ✅ JavaScript ifadelerini JSX içinde kullanma
  • ✅ Koşullu rendering teknikleri (ternary, &&, if/else)
  • ✅ Liste rendering ve key prop'unun önemi
  • ✅ Fragment kullanımı ve gereksiz wrapper'lardan kurtulma
  • ✅ Event handling ve form yönetimi
  • ✅ Props, children ve composition pattern'leri
  • ✅ JSX'te styling (inline, className)
  • ✅ Best practices ve yaygın hatalardan kaçınma

Sırada Ne Var?

Bir sonraki derste React State ve Hooks konusuna dalacağız. Bileşenlerinizin interaktif hale gelmesi için state yönetimini öğreneceksiniz.

  • 🎯 useState hook ile state yönetimi
  • 🎯 Event handler'lar ile state güncelleme
  • 🎯 Controlled vs Uncontrolled components
  • 🎯 State lifting ve component iletişimi
Pratik Yapın!

JSX öğrenmenin en iyi yolu pratik yapmaktır. Şimdi kendi bileşenlerinizi oluşturmayı deneyin:

  • 📝 Bir kullanıcı profil kartı bileşeni yapın
  • 📝 Liste filtreleme özelliği ekleyin
  • 📝 Koşullu rendering ile farklı UI durumları gösterin
  • 📝 Form component'i oluşturun
Anlayışınızı Kontrol Edin

JSX'te JavaScript ifadesi kullanmanın doğru yolu nedir?

Kalan deneme: 3 / 3