
React'ın En Büyük Mimari Güncellemesi
React ekibi, 5 Aralık 2024'te React 19'u stabil olarak yayınladı. React 16.8'de Hook'ların tanıtılmasından bu yana en büyük mimari değişiklik olarak kabul edilen bu sürüm, form yönetimi, veri akışı ve sunucu-istemci etkileşim paradigmalarını kökten değiştiriyor.
Actions: Form Yönetiminde Devrim
React 19'un amiral gemisi özelliği Actions. Artık <form> elementinin action prop'una doğrudan bir fonksiyon geçebilirsiniz. React, pending state, hata yönetimi ve iyimser güncellemeleri otomatik olarak yönetiyor:
1function ContactForm() {
2 const [state, submitAction, isPending] = useActionState(
3 async (previousState, formData) => {
4 const name = formData.get('name') as string;
5 const email = formData.get('email') as string;
6 const error = await sendMessage({ name, email });
7 if (error) return { error };
8 return { success: true };
9 },
10 null
11 );
12
13 return (
14 <form action={submitAction}>
15 <input name="name" required />
16 <input name="email" type="email" required />
17 <button disabled={isPending}>
18 {isPending ? 'Gönderiliyor...' : 'Gönder'}
19 </button>
20 {state?.error && <p className="error">{state.error}</p>}
21 {state?.success && <p className="success">Mesajınız gönderildi!</p>}
22 </form>
23 );
24}Bu yaklaşımın güzelliği, form JavaScript yüklenmeden önce de çalışıyor (progressive enhancement). useActionState hook'u hem client hem de server actions ile uyumlu.
useOptimistic: Anlık UI Güncellemeleri
Yeni useOptimistic hook'u, sunucu yanıtı gelmeden önce UI'ı güncellemenizi sağlıyor. Sosyal medya beğeni butonu veya sepete ekleme gibi işlemler için ideal:
1function LikeButton({ postId, initialLikes }: { postId: string, initialLikes: number }) {
2 const [optimisticLikes, addOptimisticLike] = useOptimistic(
3 initialLikes,
4 (current: number) => current + 1
5 );
6
7 async function handleLike() {
8 addOptimisticLike(null); // UI anında güncellenir
9 await likePost(postId); // Sunucu isteği arka planda
10 }
11
12 return (
13 <button onClick={handleLike}>
14 ❤️ {optimisticLikes}
15 </button>
16 );
17}Sunucu isteği başarısız olursa React otomatik olarak önceki değere geri döner—hiçbir ekstra kod yazmaya gerek yok.
use Hook: Promise ve Context Okuma
Yeni use hook'u, React'ın diğer hook'larından farklı olarak koşullu bloklar ve döngüler içinde çağrılabilir. Promise ve context okuma işlemlerini radikal şekilde basitleştiriyor:
1import { use, Suspense } from 'react';
2
3// Promise okuma - Suspense ile otomatik entegre
4function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
5 const user = use(userPromise);
6 return <h1>{user.name}</h1>;
7}
8
9// Koşullu context okuma - useContext ile mümkün değildi!
10function ThemeButton({ showIcon }: { showIcon: boolean }) {
11 if (showIcon) {
12 const theme = use(ThemeContext); // Koşullu blokta çağrılabilir
13 return <Icon color={theme.primary} />;
14 }
15 return <button>Tıkla</button>;
16}
17
18// Kullanım
19function App() {
20 const userPromise = fetchUser(); // await yok!
21 return (
22 <Suspense fallback={<Skeleton />}>
23 <UserProfile userPromise={userPromise} />
24 </Suspense>
25 );
26}Server Components ve Server Actions
Server Components artık stabil ve resmi olarak React'ın çekirdek parçası. Sunucuda render edilen bu bileşenler, client bundle'a dahil edilmiyor:
1// Server Component - veritabanına doğrudan erişim
2// Bu bileşen sunucuda çalışır, client'a JS göndermez
3async function BlogPosts() {
4 const posts = await db.posts.findMany({
5 orderBy: { createdAt: 'desc' },
6 take: 10
7 });
8
9 return (
10 <ul>
11 {posts.map(post => (
12 <li key={post.id}>
13 <Link href={`/blog/${post.slug}`}>{post.title}</Link>
14 </li>
15 ))}
16 </ul>
17 );
18}Server Actions, "use server" direktifi ile tanımlanan ve istemciden güvenli şekilde çağrılabilen sunucu fonksiyonları:
1// app/actions.ts
2'use server';
3
4export async function createPost(formData: FormData) {
5 const title = formData.get('title') as string;
6 const content = formData.get('content') as string;
7
8 // Sunucuda çalışır - veritabanına doğrudan erişim
9 await db.posts.create({ data: { title, content } });
10 revalidatePath('/blog');
11}
12
13// Client Component'tan kullanım
14'use client';
15import { createPost } from './actions';
16
17function NewPostForm() {
18 return (
19 <form action={createPost}>
20 <input name="title" placeholder="Başlık" />
21 <textarea name="content" placeholder="İçerik" />
22 <button type="submit">Oluştur</button>
23 </form>
24 );
25}ref Artık Bir Prop
React 19'da forwardRef wrapper'ına artık gerek yok. ref doğrudan prop olarak geçilebilir:
1// React 18 - forwardRef gerekli
2const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
3 return <input ref={ref} {...props} />;
4});
5
6// React 19 - doğrudan prop
7function Input({ ref, ...props }: InputProps & { ref?: React.Ref<HTMLInputElement> }) {
8 return <input ref={ref} {...props} />;
9}
10
11// Ref callback cleanup
12function MeasuredDiv() {
13 return (
14 <div ref={(node) => {
15 // Node oluşturulduğunda
16 if (node) measureElement(node);
17
18 // Cleanup fonksiyonu - node kaldırılırken
19 return () => cleanupMeasurement();
20 }}>
21 İçerik
22 </div>
23 );
24}Document Metadata ve Stylesheet Desteği
Artık <title>, <meta> ve <link> etiketlerini doğrudan bileşen içinden render edebilirsiniz:
1function BlogPost({ post }: { post: Post }) {
2 return (
3 <article>
4 <title>{post.title} | Blog</title>
5 <meta name="description" content={post.excerpt} />
6 <meta property="og:title" content={post.title} />
7 <link rel="canonical" href={`https://siyaz.com.tr/blog/${post.slug}`} />
8
9 <h1>{post.title}</h1>
10 <p>{post.content}</p>
11 </article>
12 );
13}
14// React bunları otomatik olarak <head> içine taşır (hoisting)Önceki Sürümlerle Karşılaştırma
| Özellik | React 18 | React 19 |
|---|---|---|
| Form yönetimi | Manuel state + handler | useActionState + Actions |
| İyimser güncelleme | Kendi implementasyonun | useOptimistic |
| Promise okuma | useEffect + state | use hook |
| Ref geçirme | forwardRef wrapper | Doğrudan prop |
| Metadata | react-helmet / next/head | Native hoisting |
| Server Components | Framework-dependent | React core |
| Context okuma | useContext (koşulsuz) | use (koşullu da olabilir) |
| Ref cleanup | Desteklenmiyor | Callback return |
React Compiler (Deneysel)
React Compiler, useMemo, useCallback ve React.memo ihtiyacını ortadan kaldıran bir build-time optimizasyon aracı:
1// React 18 - Manuel memoization
2function ProductList({ products, onSelect }) {
3 const sorted = useMemo(
4 () => products.sort((a, b) => a.price - b.price),
5 [products]
6 );
7 const handleSelect = useCallback(
8 (id) => onSelect(id),
9 [onSelect]
10 );
11 return sorted.map(p => <Product key={p.id} item={p} onSelect={handleSelect} />);
12}
13
14// React 19 + Compiler - Otomatik optimizasyon
15function ProductList({ products, onSelect }) {
16 const sorted = products.sort((a, b) => a.price - b.price);
17 const handleSelect = (id) => onSelect(id);
18 return sorted.map(p => <Product key={p.id} item={p} onSelect={handleSelect} />);
19}
20// Compiler, gerekli yerlere otomatik memoization eklerInstagram.com'da production'da test edildi ve olumlu sonuçlar alındı.
Sonuç
React 19, kütüphanenin sunucu taraflı render ve form yönetimi vizyonunu somutlaştıran tarihi bir sürüm. Özellikle Next.js 15 ve Remix gibi framework'lerle birlikte kullanıldığında tam potansiyelini ortaya koyuyor.
Geliştiriciler için en büyük değişiklik, mental model. React artık "sadece UI kütüphanesi" değil—sunucu ve istemci arasında sorunsuz veri akışı sağlayan full-stack bir çözüm. AI kod editörleri de React 19 pattern'larını hızla öğreniyorlar.
Kaynaklar:


