İçeriğe geç
react

React 19 Yenilikleri: Kapsamlı İnceleme

Tarık Tunç
React 19 Yenilikleri: Kapsamlı İnceleme

React 19 Yenilikleri: Kapsamlı İnceleme

React 19, React ekosisteminde büyük değişiklikler getiren önemli bir sürümdür. Actions, yeni hook'lar, React Compiler, geliştirilmiş Server Components ve daha birçok yenilik içerir. Bu yazıda React 19'un tüm önemli özelliklerini detaylı kod örnekleriyle inceleyeceğiz.

Actions ve Form Yönetimi

React 19'un en büyük yeniliklerinden biri Actions kavramıdır. Actions, asenkron işlemleri (veri gönderme, form submit) yönetmek için yeni bir paradigma sunar. Pending state, hata yönetimi ve optimistic update'ler otomatik olarak ele alınır.

import { useActionState } from 'react';

function LoginForm() {
  const [state, formAction, isPending] = useActionState(
    async (previousState, formData) => {
      const email = formData.get('email');
      const password = formData.get('password');

      try {
        const result = await loginUser({ email, password });
        return { success: true, message: 'Giriş başarılı!' };
      } catch (error) {
        return { success: false, message: error.message };
      }
    },
    { success: false, message: '' }
  );

  return (
    <form action={formAction}>
      <input name="email" type="email" placeholder="E-posta" required />
      <input name="password" type="password" placeholder="Şifre" required />

      {state.message && (
        <p className={state.success ? 'success' : 'error'}>
          {state.message}
        </p>
      )}

      <button type="submit" disabled={isPending}>
        {isPending ? 'Giriş yapılıyor...' : 'Giriş Yap'}
      </button>
    </form>
  );
}

useOptimistic Hook'u

useOptimistic, kullanıcıya anında geri bildirim vermek için optimistic UI güncellemeleri yapmanızı sağlar. İşlem başarısız olursa önceki state'e otomatik geri döner.

import { useOptimistic } from 'react';

function TodoList({ todos, addTodo }) {
  const [optimisticTodos, addOptimisticTodo] = useOptimistic(
    todos,
    (currentTodos, newTodo) => [
      ...currentTodos,
      { ...newTodo, id: Date.now(), pending: true },
    ]
  );

  async function handleSubmit(formData) {
    const title = formData.get('title');
    const newTodo = { title, completed: false };

    // Optimistic güncelleme — anında UI'da göster
    addOptimisticTodo(newTodo);

    // Gerçek API çağrısı
    await addTodo(newTodo);
    // Başarısız olursa React otomatik geri alır
  }

  return (
    <div>
      <form action={handleSubmit}>
        <input name="title" placeholder="Yeni görev..." required />
        <button type="submit">Ekle</button>
      </form>

      <ul>
        {optimisticTodos.map((todo) => (
          <li key={todo.id} style={{ opacity: todo.pending ? 0.6 : 1 }}>
            {todo.title}
            {todo.pending && <span> (kaydediliyor...)</span>}
          </li>
        ))}
      </ul>
    </div>
  );
}

useFormStatus Hook'u

useFormStatus, form'un mevcut durumunu (pending, data, method, action) alt bileşenlerden okumak için kullanılır.

import { useFormStatus } from 'react-dom';

function SubmitButton({ children }) {
  const { pending, data, method } = useFormStatus();

  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Gönderiliyor...' : children}
    </button>
  );
}

function ContactForm() {
  async function handleSubmit(formData) {
    await sendMessage(formData);
  }

  return (
    <form action={handleSubmit}>
      <input name="name" placeholder="İsim" required />
      <textarea name="message" placeholder="Mesaj" required />
      <SubmitButton>Gönder</SubmitButton>
    </form>
  );
}

use() API

use(), Promise'leri ve Context'i doğrudan render sırasında okumanızı sağlayan yeni bir API'dir. Koşullu olarak çağrılabilir, bu onu hook'lardan ayırır.

import { use, Suspense } from 'react';

// Promise okuma
function UserProfile({ userPromise }) {
  const user = use(userPromise);
  return (
    <div>
      <h3>{user.name}</h3>
      <p>{user.email}</p>
    </div>
  );
}

function App() {
  const userPromise = fetchUser(1); // Promise döner

  return (
    <Suspense fallback={<p>Yükleniyor...</p>}>
      <UserProfile userPromise={userPromise} />
    </Suspense>
  );
}

// Koşullu Context okuma
function ThemeText({ showTheme }) {
  if (showTheme) {
    const theme = use(ThemeContext);
    return <p>Tema: {theme}</p>;
  }
  return <p>Tema gizli</p>;
}

React Compiler

React Compiler (eski adıyla React Forget), bileşenleri ve hook'ları otomatik olarak memoize eder. useMemo, useCallback ve React.memo kullanımına olan ihtiyacı büyük ölçüde azaltır.

// React Compiler öncesi — manuel optimizasyon
function ProductList({ products, category }) {
  const filtered = useMemo(
    () => products.filter((p) => p.category === category),
    [products, category]
  );

  const handleClick = useCallback((id) => {
    navigate(`/product/${id}`);
  }, []);

  return filtered.map((p) => (
    <ProductCard key={p.id} product={p} onClick={handleClick} />
  ));
}

// React Compiler sonrası — otomatik optimizasyon
function ProductList({ products, category }) {
  const filtered = products.filter((p) => p.category === category);

  const handleClick = (id) => {
    navigate(`/product/${id}`);
  };

  // Compiler otomatik olarak gerekli memoization'ı ekler
  return filtered.map((p) => (
    <ProductCard key={p.id} product={p} onClick={handleClick} />
  ));
}
// babel.config.js — React Compiler kurulumu
module.exports = {
  plugins: [
    ['babel-plugin-react-compiler', {
      // Compiler yapılandırması
    }],
  ],
};

ref Prop Olarak Kullanma

React 19'da forwardRef artık gerekli değildir. ref doğrudan bir prop olarak geçirilebilir.

// React 18 — forwardRef gerekli
const Input = forwardRef(function Input(props, ref) {
  return <input ref={ref} {...props} />;
});

// React 19 — ref doğrudan prop olarak
function Input({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

// Kullanım aynı kalır
function Form() {
  const inputRef = useRef(null);
  return <Input ref={inputRef} placeholder="İsim" />;
}

Document Metadata Desteği

React 19, <title>, <meta> ve <link> etiketlerini bileşenler içinde doğrudan render etmenize olanak tanır. React, bunları otomatik olarak <head> içine taşır.

function ProductPage({ product }) {
  return (
    <article>
      <title>{product.name} | Mağaza</title>
      <meta name="description" content={product.description} />
      <meta property="og:title" content={product.name} />
      <link rel="canonical" href={`/products/${product.slug}`} />

      <h1>{product.name}</h1>
      <p>{product.description}</p>
    </article>
  );
}

Stylesheet ve Script Desteği

function Dashboard() {
  return (
    <div>
      {/* React, stylesheet'i head'e taşır ve yüklenene kadar bekler */}
      <link rel="stylesheet" href="/dashboard.css" precedence="default" />

      {/* Async script desteği */}
      <script src="/analytics.js" async />

      <h1>Dashboard</h1>
    </div>
  );
}

Geliştirilmiş Hata Raporlama

React 19, hydration hataları ve diğer hata mesajlarını çok daha anlaşılır hale getirir:

// React 18 — belirsiz hata mesajı
// "Text content does not match server-rendered HTML"

// React 19 — detaylı diff gösterimi
// "Hydration failed because the server rendered HTML didn't match the client.
//  Server: <div>Hello</div>
//  Client: <div>World</div>"
İpucu: React 19'a geçiş yaparken, mevcut forwardRef kullanımlarınızı hemen kaldırmanız gerekmez. React 19 geriye uyumludur ve forwardRef hala çalışır. Ancak yeni bileşenlerde doğrudan ref prop kullanımını tercih edin.

Yeni Hook'lar Özet Tablosu

Hook Amaç Import
useActionState Form action state yönetimi react
useFormStatus Form pending durumu okuma react-dom
useOptimistic Optimistic UI güncellemeleri react
use Promise ve Context okuma react
Uyarı: React 19'da bazı eski API'ler kaldırılmıştır: propTypes, defaultProps (fonksiyon bileşenlerde), createFactory, render (react-dom yerine createRoot kullanın), string ref'ler ve Legacy Context. Geçiş yapmadan önce codemod'ları çalıştırın.

Sonuç

React 19, form yönetimini Actions ile basitleştiren, useOptimistic ile kullanıcı deneyimini iyileştiren, React Compiler ile manuel optimizasyon yükünü kaldıran ve birçok DX iyileştirmesi getiren kapsamlı bir sürümdür. forwardRef'in kaldırılması, native metadata desteği ve geliştirilmiş hata mesajları günlük geliştirme deneyimini önemli ölçüde iyileştirir. Yeni projelerde React 19 ile başlamak, mevcut projelerde ise kademeli geçiş yapmak en iyi stratejidir.

Kaynaklar

İlgili Yazılar