React 19, React ekosisteminde uzun süredir konuşulan iki büyük başlığı aynı sürümde birleştiriyor: form ve veri akışlarını basitleştiren yeni API'ler ile derleme zamanında otomatik optimizasyon yapan React Compiler. Bu rehber, orta seviye bir React geliştiricisinin bu değişiklikleri mevcut kod tabanına kontrollü biçimde taşımasına odaklanır.
Önkoşullar ve kapsam
- React ve hooks (
useState,useEffect,useContext,useRef) ile rahat çalışıyor olmanız beklenir. - Örnekler fonksiyonel bileşen ve modern JSX varsayar.
- React Compiler deneysel bir araçtır; API yüzeyi ve yapılandırma seçenekleri sürümden sürüme değişebilir. Bu nedenle burada belirli bir sürüm numarası vermek yerine, kurulumu resmi dokümantasyondaki güncel talimatlara göre yapmanız gerekir.
- React 19'un getirdiği API'lerin kesin davranışı ve kararlılık durumu için resmi React sürüm notlarını ve dokümantasyonunu esas alın.
React 19'da öne çıkan API'ler
Actions ve form yönetimi
React 19, asenkron işlemleri (özellikle form gönderimlerini) birinci sınıf vatandaş haline getirir. Bileşen içinde bir async fonksiyonu action olarak tanımlayıp form ile ilişkilendirebilirsiniz. Bu model, "gönderiliyor / hata / sonuç" durumlarını elle yönetme ihtiyacını azaltır.
function KayitFormu() {
async function gonder(formData) {
const ad = formData.get("ad");
await kayitOl({ ad });
}
return (
<form action={gonder}>
<input name="ad" />
<button type="submit">Kaydol</button>
</form>
);
}
Burada action prop'una doğrudan bir fonksiyon verilir. React, gönderim sırasında formun yaşam döngüsünü yönetir. Beklenen davranış: kullanıcı gönder'e bastığında gonder çağrılır ve formData doğrudan bu fonksiyona iletilir; event.preventDefault() yazmanız gerekmez.
useActionState ile durum takibi
Action'ın döndürdüğü sonucu ve bekleyen (pending) durumunu izlemek için useActionState kullanılır. Bu hook, action'ı bir state makinesine bağlar.
import { useActionState } from "react";
function KayitFormu() {
const [durum, formAction, isPending] = useActionState(
async (oncekiDurum, formData) => {
const ad = formData.get("ad");
if (!ad) return { hata: "Ad zorunlu" };
await kayitOl({ ad });
return { basarili: true };
},
null
);
return (
<form action={formAction}>
<input name="ad" />
<button disabled={isPending}>Kaydol</button>
{durum?.hata && <p>{durum.hata}</p>}
</form>
);
}
Beklenen davranış: action çalışırken isPending true olur ve buton devre dışı kalır; action döndüğünde durum güncellenir. İlk argüman olarak önceki durumu alan imza, ardışık gönderimlerde tutarlılık sağlar.
useOptimistic ile iyimser güncelleme
Sunucu yanıtı gelmeden arayüzü güncellemek istediğinizde useOptimistic devreye girer. Amaç, algılanan gecikmeyi azaltmaktır; gerçek veri geldiğinde geçici durum otomatik olarak geri alınır.
import { useOptimistic } from "react";
function MesajListesi({ mesajlar, gonderAction }) {
const [optimistik, ekleOptimistik] = useOptimistic(
mesajlar,
(mevcut, yeni) => [...mevcut, { metin: yeni, gecici: true }]
);
return (
<form
action={async (formData) => {
ekleOptimistik(formData.get("metin"));
await gonderAction(formData);
}}
>
<ul>
{optimistik.map((m, i) => (
<li key={i}>{m.metin}</li>
))}
</ul>
<input name="metin" />
<button type="submit">Gönder</button>
</form>
);
}
Beklenen davranış: ekleOptimistik çağrıldığı anda liste geçici olarak büyür; action tamamlanınca React, gerçek mesajlar prop'una geri döner. İyimser durum yalnızca action süresince geçerlidir.
use hook'u
use, Promise veya context okuyabilen yeni bir API'dir. useContext'ten farklı olarak koşullu ifadelerin içinde çağrılabilir.
import { use } from "react";
function Yorumlar({ yorumPromise }) {
const yorumlar = use(yorumPromise);
return <ul>{yorumlar.map((y) => <li key={y.id}>{y.metin}</li>)}</ul>;
}
use ile bir Promise okunduğunda, Promise çözülene kadar bileşen askıya alınır (Suspense). Bu nedenle ilgili bileşeni bir <Suspense> sınırı ile sarmalamanız beklenir. Bu API'yi kullanırken Promise'ı her render'da yeniden oluşturmamaya dikkat edin; aksi halde gereksiz askıya almalar yaşanır.
React Compiler (Forget)
React Compiler, useMemo, useCallback ve React.memo gibi elle yapılan optimizasyonları derleme zamanında otomatikleştirmeyi amaçlar. "Forget" adı, geliştiricinin memoizasyonu "unutması" fikrinden gelir.
Temel fikir şudur: Derleyici, bileşenlerinizin veri akışını analiz eder ve yeniden render maliyetini azaltacak memoizasyonu sizin adınıza ekler. Bu, kodunuzu değiştirmeden çalışır ancak derleyicinin analiz edebilmesi için kodun belirli kurallara uyması gerekir.
Derleyicinin beklediği kurallar
- Bileşenler ve hook'lar saf (pure) olmalıdır; render sırasında dış durumu değiştirmemelidir.
- Render sırasında prop veya state mutasyonu yapılmamalıdır.
- Hook'lar koşullu olarak çağrılmamalıdır; çağrı sırası sabit olmalıdır.
- Ref'ler render sırasında okunmamalı veya yazılmamalıdır.
Bu kurallar zaten React'in genel kurallarıdır; derleyici bunlara uyulmadığında optimizasyonu atlar veya kodunuzu derleyemez.
Kurulum ve devreye alma yaklaşımı
Derleyiciyi projeye eklerken kademeli ilerleyin:
- Önce derleyicinin kod tabanınızı analiz edip edemediğini kontrol edin; derleyici genellikle analiz edemediği bileşenler hakkında uyarı verir.
- Küçük bir modül veya dizin üzerinde etkinleştirip davranışın değişmediğini doğrulayın.
- Testleriniz yeşil kaldığı sürece kapsamı genişletin.
Belirli paket adları, kurulum komutları ve yapılandırma anahtarları sürüme göre değiştiği için bunları resmi React Compiler dokümantasyonundan almanız gerekir. Bu rehberde uydurulmuş bir yapılandırma örneği vermek yerine, resmi kaynağı takip etmenizi öneririm.
Elle memoizasyonla ilişkisi
Derleyici etkinken mevcut useMemo/useCallback çağrılarınızı toplu halde silmeyin. Önce derleyicinin bu bileşenleri optimize edip etmediğini doğrulayın; ardından gereksiz hale gelenleri kademeli olarak kaldırın. Bazı durumlarda elle memoizasyon hâlâ anlamlı olabilir (örneğin, derleyicinin analiz edemediği üçüncü parti kodlarla etkileşimde).
Yaygın hatalar
- Action'da
event.preventDefault()beklemek:actionprop'una fonksiyon verdiğinizde React form gönderimini yönetir; elle engelleme eklemek gereksizdir ve beklenmeyen davranışa yol açabilir. useile her render'da yeni Promise üretmek: Promise'ı bileşen gövdesinde oluşturmak, her render'da askıya alınmaya neden olur. Promise'ı dışarıda oluşturup prop olarak iletin.- İyimser durumu kalıcı sanmak:
useOptimisticile eklenen veri, action bittiğinde kaybolur. Kalıcılık için gerçek veri kaynağını güncellemeniz gerekir. - Derleyiciyi kurallara uymayan kodla zorlamak: Kural ihlalleri derleyicinin optimizasyonu atlamasına yol açar; önce kodu kurallara uygun hale getirin.
Güvenlik ve veri akışı notları
- Form action'ları sunucu tarafında da doğrulanmalıdır. İstemci tarafındaki iyimser güncelleme ve doğrulama, sunucu doğrulamasının yerini tutmaz.
useile okuduğunuz Promise'ların kaynağını kontrol edin; kullanıcı girdisinden doğrudan üretilen Promise'lar, beklenmeyen veri akışlarına açık kapı bırakabilir.- Derleyici, kodunuzun davranışını değiştirmez; yalnızca performansı etkiler. Güvenlik açıkları derleyicinin kapsamı dışındadır, bu yüzden mevcut güvenlik pratiklerinizi koruyun.
Sonuç
React 19'un action tabanlı API'leri form ve asenkron veri akışını sadeleştirirken, React Compiler memoizasyon yükünü derleme zamanına taşıyor. Her iki yeniliği de üretime almadan önce sürüm notlarını ve resmi dokümantasyonu takip edin; kademeli etkinleştirme ve testlerle ilerlemek, beklenmeyen davranış değişikliklerini erken yakalamanın en güvenilir yoludur.