Tüm Yazılar
KategoriFull-Stack
Okuma Süresi
13 dk
Yayın Tarihi
2026-08-05
Kelime Sayısı
2.659kelime

Kahveni hazırla - bu içerikli bir makale!

React 19.2: Activity, useEffectEvent ve cacheSignal

Özet

React 19.2 ile gelen Activity, useEffectEvent ve cacheSignal API'lerini gerçek kod örnekleriyle, hangi sorunu çözdüklerini ve migrasyon adımlarını inceliyoruz.

  • Activity bileşeni hidden modda çocukları display:none ile gizler, Effect'lerini temizler ama state'i korur — visible'a dönünce state ve DOM geri yüklenir.
  • useEffectEvent, Effect içindeki olay-benzeri mantığı reaktif mantıktan ayırır; dönen fonksiyon en güncel değerleri görür ama dependency array'e girmez.
  • cacheSignal render sırasında bir AbortSignal döner, render tamamlanınca/iptal olunca abort edilir; render dışında null döner.
  • useEffectEvent kullanmadan önce eslint-plugin-react-hooks paketini @latest sürümüne yükseltmek gerekir (react.dev 19.2 duyurusunun önerisi).
React 19.2: Activity, useEffectEvent ve cacheSignal

React 19.2, npm'e 1 Ekim 2025'te düştüğünde üç API aynı anda gündeme geldi: <Activity>, useEffectEvent ve cacheSignal. React ekibinin kendi ifadesiyle bu, son bir yılın üçüncü sürümüydü — Aralık'taki React 19'un ve ardından gelen React 19.1'in üçüncü halkası. Bu yazıda React 19.2 Activity API'sini, useEffectEvent hook'unu ve cacheSignal mekanizmasını gerçek kod örnekleriyle, hangi problemi çözdükleriyle ve bugün bir projeye nasıl taşınacaklarıyla göreceksin.

💡 Pro Tip: eslint-plugin-react-hooks'u @latest'e yükselt (5 Ağustos 2026 itibarıyla latest 7.1.1) — aksi halde linter, Effect Event fonksiyonlarını dependency array'ine eklemeye çalışır.

İçindekiler

19.2 Hattında Ne Var, Hangi Sürüm Güncel

React 19.2, 1 Ekim 2025'te react.dev üzerinden duyuruldu ve aynı gün npm'e yayınlandı. React ekibi bu sürümü son bir yılın üçüncü sürümü olarak tanımlıyor: Aralık 2024'te React 19, ardından React 19.1, ardından Ekim 2025'te React 19.2 (duyuru metni 19.1 için Haziran diyor; npm registry ve react.dev/versions ise 19.1.0'ı 28 Mart 2025 gösteriyor). Bu makalenin yazıldığı tarih (5 Ağustos 2026) itibarıyla 19.2 hattı hâlâ aktif bakım alıyor; npm registry kayıtlarına göre en son patch olan 19.2.8, 21 Temmuz 2026'da yayınlandı.

Sürüm
Yayın
Not
React 19.0
Aralık 2024
Ana 19 sürümü
React 19.1
Mart 2025
Ara sürüm
React 19.2.0
1 Ekim 2025
Activity, useEffectEvent, cacheSignal tanıtıldı
React 19.2.8
21 Temmuz 2026
Son 19.2 patch (npm registry time verisi)

Bu tabloda dikkat çeken nokta şu: react.dev'in kendi "Releases" sayfası 19.2.8'i ayrı bir satır olarak listelemiyor — sayfa 19.2.7'den sonra patch satırı eklemiyor. Patch seviyesindeki gerçek tarihi görmek için npm registry'nin time alanına bakmak gerekiyor; bu da React'in resmi changelog sayfasının patch-seviyesinde güncel olmayabileceğini gösteriyor — üretim ortamında hangi sürümü çalıştırdığını doğrularken tek başına react.dev'e güvenmemek, npm view react versions veya registry sorgusuyla çapraz kontrol etmek daha güvenli.

19.2'nin üç ana API'sinin ortak noktası şu: hepsi de "React zaten yapıyordu ama sana kontrol vermiyordu" dediğin bir alanı açıyor. Activity React'in zaten iç mekanizmasında var olan gizleme/gösterme davranışını sana bir bileşen olarak sunuyor; useEffectEvent Effect'lerin içinde zaten ayrışmış olması gereken iki farklı mantığı (reaktif ve olay-benzeri) resmi bir API ile ayırıyor; cacheSignal ise sunucu render'ının zaten bir yaşam döngüsü olduğunu, bu döngünün artık dinlenebilir olduğunu gösteriyor. Üçü de "yeni bir yetenek" değil, var olan bir davranışı öngörülebilir ve test edilebilir hale getiriyor.

Activity: Gizle-Ama-Durumu-Koru Pattern'i

<Activity>, uygulamanı kontrol edilebilir ve önceliklendirilebilir parçalara bölmeni sağlayan yeni bir bileşen. İki modu var: visible ve hidden. mode prop'u verilmezse varsayılan olarak visible kabul ediliyor.

hidden moduna geçtiğinde React, çocukları display: "none" CSS özelliğiyle görsel olarak gizliyor, onların Effect'lerini yok ediyor (temizliyor) ama state'i koruyor. Tekrar visible'a döndüğünde React, önceki state'i geri yükleyerek çocukları gösteriyor ve Effect'lerini yeniden oluşturuyor. Gizliyken çocuklar hâlâ yeni prop'lara göre yeniden render oluyor — ama görünür içerikten daha düşük öncelikte.

tsx
1import { Activity, useState } from "react";
2 
3function App() {
4 const [tab, setTab] = useState<"feed" | "profile">("feed");
5 
6 return (
7 <>
8 <Activity mode={tab === "feed" ? "visible" : "hidden"}>
9 <FeedPage />
10 </Activity>
11 <Activity mode={tab === "profile" ? "visible" : "hidden"}>
12 <ProfilePage />
13 </Activity>
14 </>
15 );
16}

Bu örnekte tab değeri "profile" olduğunda FeedPage DOM'dan kaldırılmıyor, yalnızca gizleniyor — scroll pozisyonu, form state'i ve iç bileşen state'i korunuyor. Koşullu render ({isVisible && <FeedPage />}) kullansaydın, FeedPage her seferinde sıfırdan mount olurdu.

Mod
Görünürlük
Effect'ler
State
visible
gizleme uygulanmaz, normal render
mount edilir, çalışır
korunur
hidden
display: none
unmount edilir (temizlenir)
korunur, düşük öncelikli güncellenir

Pratikte en tipik kullanım alanı, mobil uygulamalardaki alt sekme çubuğuna (tab bar) benzeyen yapılar. Kullanıcı "Feed" sekmesinden "Profil"e geçtiğinde, klasik koşullu render ile FeedPage tamamen unmount olur; kullanıcı geri döndüğünde scroll pozisyonu sıfırlanır, açık filtreler kaybolur, network isteği yeniden atılır. Activity ile bu sekme hidden moda geçer ama DOM'da kalır — geri dönüldüğünde her şey kaldığı yerden devam eder. Bunun bedeli, gizli sekmelerin bellekte tutulmaya devam etmesidir; bu yüzden Activity'yi her bileşende değil, kullanıcı deneyimi state kaybından gerçekten zarar gören akışlarda (çok adımlı formlar, sekmeli dashboard'lar, arama sonuçları) kullanmak mantıklı.

useEffectEvent ile Bağımlılık Dizisi Cehennemi

Klasik bir problem: useEffect içinde hem bağlantı kurma gibi "reaktif" mantık hem de bildirim gösterme gibi "olay benzeri" mantık bir arada bulunuyor. İkincisi bir değere (örneğin theme) bağımlıysa, o değer değiştiğinde tüm Effect gereksiz yere yeniden çalışıyor.

tsx
1// ÖNCE: theme değiştiğinde sohbet odası gereksiz yeniden bağlanır
2function ChatRoom({ roomId, theme }: { roomId: string; theme: string }) {
3 useEffect(() => {
4 const connection = createConnection(roomId);
5 connection.on("connected", () => {
6 showNotification("Bağlandı!", theme);
7 });
8 connection.connect();
9 return () => connection.disconnect();
10 }, [roomId, theme]); // theme değişince de yeniden bağlanır
11}

useEffectEvent, bu "olay" kısmını Effect'ten ayırıyor. Effect Event'ler render'daki en güncel prop/state değerlerini her zaman görüyor ama dependency array'e girmiyor — çünkü kimlikleri (identity) kasıtlı olarak her render'da değişiyor; bu bilinçli bir tasarım kararı.

tsx
1// SONRA: theme artık dependency değil, ama en güncel değeri görüyor
2import { useEffectEvent, useEffect } from "react";
3 
4function ChatRoom({ roomId, theme }: { roomId: string; theme: string }) {
5 const onConnected = useEffectEvent(() => {
6 showNotification("Bağlandı!", theme);
7 });
8 
9 useEffect(() => {
10 const connection = createConnection(roomId);
11 connection.on("connected", () => onConnected());
12 connection.connect();
13 return () => connection.disconnect();
14 }, [roomId]); // theme artık burada yok
15}

İki kural önemli: useEffectEvent yalnızca component veya Hook'un en üst seviyesinde çağrılabilir (döngü/koşul içinde olmaz), ve dönen fonksiyon yalnızca Effect'ler veya başka Effect Event'ler içinden çağrılabilir.

Aynı desen analytics/telemetri kodunda da sık görülüyor. Bir sayfa görüntüleme olayını, sayfanın kendisi değişmeden yalnızca kullanıcı kimliği veya oturum bilgisi değiştiğinde tekrar tetiklemek istemezsin — ama olay fırlatıldığı anda en güncel kullanıcı bilgisini kullanmak istersin:

tsx
1import { useEffectEvent, useEffect } from "react";
2 
3function ProductPage({
4 productId,
5 userId,
6}: {
7 productId: string;
8 userId: string;
9}) {
10 const logPageView = useEffectEvent((id: string) => {
11 analytics.track("product_view", { productId: id, userId });
12 });
13 
14 useEffect(() => {
15 logPageView(productId);
16 }, [productId]); // userId dependency'de yok, ama olay her zaman güncel userId'yi görür
17}

Burada userId değiştiğinde sayfa görüntüleme olayı tekrar tetiklenmiyor — çünkü bu mantıksal olarak yanlış olurdu (kullanıcı sayfayı tekrar görüntülemedi, sadece oturumu değişti). Ama logPageView çağrıldığında her zaman en güncel userId değerini kullanıyor. Bu ayrım, useEffectEvent olmadan ya eslint-disable ile bastırılan bir uyarıya ya da gereksiz yeniden tetiklenmeye yol açardı. Dikkat: useEffectEvent'i "gereksiz" bağımlılıkları gizlemek için kullanma — react.dev bunu anti-pattern sayıyor.

cacheSignal ve Sunucu Tarafı İptal

cacheSignal, render sırasında çağrıldığında bir AbortSignal döndürüyor; render dışında çağrılırsa null dönüyor. Bu sinyal, cache() ile sarılmış bir işlemin (örneğin fetch veya DB sorgusu) ömrünü takip etmeni sağlıyor: React render'ı tamamladığında, iptal ettiğinde veya hata aldığında sinyal abort ediliyor. cacheSignal şu an yalnızca Server Component'lerde kullanılabiliyor; Client Component içinde çağrılırsa her zaman null dönüyor.

tsx
1import { cache, cacheSignal } from "react";
2 
3const dedupedFetch = cache(fetch);
4 
5async function Component({ url }: { url: string }) {
6 const response = await dedupedFetch(url, {
7 signal: cacheSignal() ?? undefined,
8 });
9 const data = await response.json();
10 return <DataView data={data} />;
11}

Pratikte bu, sunucu tarafı render'ı erken sonlandığında (örneğin render abort edildiğinde veya bir üst Suspense sınırı hata fırlattığında) devam eden fetch isteklerinin boşuna tamamlanmasını önlüyor — sinyal abort edildiğinde fetch de iptal edilebiliyor.

Bu, özellikle çok sayıda paralel veri kaynağı olan Server Component ağaçlarında değer kazanıyor. Bir dashboard sayfasında birden fazla cache()'lenmiş sorgu paralel çalışıyorsa, cacheSignal olmadan bu sorgular render abort edilmiş olsa bile arka planda tamamlanmayı sürdürebilir. cacheSignal()'ı her isteğe bağlamak, React'in kendi render yaşam döngüsünü tek bir iptal noktasına indirgemeni sağlıyor — ayrı bir AbortController yönetmene, timeout kurmana veya component unmount'unu manuel izlemene gerek kalmıyor.

Next.js 16.3 ile Birlikte Anlamı

cacheSignal özellikle sunucu render'ının iptal edilebilir hale geldiği ortamlarda değer kazanıyor, ve Next.js 16.3 tam da bu yöne odaklanan bir sürüm. Next.js 16.3'ün sürüm notunda iki ana özellik bölümü öne çıkıyor (ayrıca deneysel özellikler için ayrı bir bölüm var). "Improvements for today's apps" bölümündeki "Fewer prefetch requests", link'lerin daha küçük payload'ları paketleyerek daha az prefetch isteği tetiklemesini sağlıyor. Ayrı bir bölüm olan "Instant Navigations" ise opt-in bir araç seti; altında "Instant Insights" (yavaş navigasyonları yüzeye çıkaran bir devtool) ve "Partial Prefetching" (bir link'in hedef sayfadan ne kadar içerik prefetch edeceğini ince ayarla kontrol etme) yer alıyor. Bu değişiklikler React'in cacheSignal API'siyle doğrudan bağlı değil, ayrı bir Next.js sürüm notu; ama ikisi de aynı yöne işaret ediyor: sunucu tarafı render ve prefetch işlemleri artık daha ayrıntılı kontrol edilebiliyor ve gerektiğinde erken sonlandırılabiliyor. cache() içinde cacheSignal() kullanan bir Server Component, altındaki framework'ün prefetch stratejisi ne olursa olsun, render'ı erken kesildiğinde artık gereksiz işi kendiliğinden durdurabiliyor.

Migrasyon: Hangi Kod Bugün Değişmeli

useEffectEvent'e geçmeden önce iki adım gerekiyor:

  • Lint paketini yükselt: eslint-plugin-react-hooks paketini @latest'e çek — aksi halde linter Effect Event'leri dependency olarak eklemeye çalışıyor.
  • "Olay" mantığını ayır: Effect içindeki bildirim/log/analytics gibi "olay benzeri" kod parçalarını useEffectEvent içine taşı, yalnızca gerçekten reaktif olan (bağlantı, subscription) kısmı Effect'te bırak.
bash
1npm install eslint-plugin-react-hooks@latest --save-dev

Activity tarafında ise mevcut koşullu render bloklarını ({isVisible && <Page />}) <Activity mode="visible|hidden"> ile değiştirmek, özellikle sekme/tab yapılarında ve form state'i korunması gereken çok adımlı akışlarda anlamlı. cacheSignal içinse mevcut cache() sarmalı fetch çağrılarına signal: cacheSignal() ?? undefined eklemek tek satırlık bir değişiklik.

Migrasyon sırasında en çok atlanan adım, useEffectEvent'in "yalnızca Effect içinden çağrılabilir" kuralını unutmak. Bir Effect Event'i render sırasında doğrudan çağırmaya çalışırsan React hata fırlatır; bir click handler'a aktarıp oradan çağırmaya çalışırsan bunu eslint-plugin-react-hooks linter'ı hata olarak işaretler — bu kasıtlı bir kısıtlama, çünkü Effect Event'ler yalnızca yerel olarak çağrılabiliyor ve başka bileşenlere aktarılamıyor veya dependency array'e eklenemiyor; bu yüzden kararlı bir kimlik (stable identity) hiçbir işe yaramaz, hatta hataları maskeleyebilirdi. Mevcut kod tabanında büyük bir useEffectEvent taraması yapmadan önce, önce en çok "eslint-disable" yorumu içeren Effect'leri hedeflemek en yüksek getiriyi sağlıyor — çünkü o satırlar zaten dependency array probleminin var olduğunun işareti.

React Compiler ile İlişkisi

React Compiler'ın ilk kararlı sürümü (v1.0), React 19.2'den bir hafta sonra, 7 Ekim 2025'te yayınlandı. Compiler, gereksiz re-render'ları otomatik olarak önlemeye odaklanıyor; Activity, useEffectEvent ve cacheSignal ise farklı problemleri çözüyor (görünürlük/state koruma, Effect bağımlılık yönetimi, sunucu iptali). İkisi birbirini dışlamıyor — Compiler'ı etkinleştirmiş bir projede bu üç API de aynı şekilde çalışmaya devam ediyor, çünkü Compiler render optimizasyonuyla ilgilenirken bu üçü farklı bir katmanda (yaşam döngüsü, olay ayrımı, iptal) konumlanıyor.

Bunun pratik sonucu şu: Compiler'ı devreye aldığında useMemo/useCallback sarmalarının çoğunu elle yazmayı bırakabilirsin, ama bu useEffectEvent'e olan ihtiyacı ortadan kaldırmıyor — çünkü Compiler render'ı optimize ediyor, Effect'in ne zaman ve neden yeniden çalışması gerektiğine dair kararı vermiyor. Aynı şekilde Compiler, Activity'nin state-koruma davranışını da değiştirmiyor; ikisi bağımsız katmanlarda çalıştığı için migrasyon sırasını (önce Compiler mi, önce bu üç API mi) istediğin gibi seçebilirsin.

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

Okuyucu Ödülü

Bu makaledeki üç API'yi kendi projene taşırken izleyebileceğin somut bir kontrol listesi hazırladık. Her maddeyi tek tek işaretleyerek migrasyonu adım adım tamamlayabilirsin.

SSS

React'te Activity component ne işe yarar?

<Activity mode={visible|hidden}>, bir UI parçasını koşullu render yerine "arka planda tutma" mekanizmasıyla yönetmeni sağlıyor. hidden modda çocuklar display: none ile gizleniyor, Effect'leri temizleniyor ama state korunuyor; visible'a dönünce state ve DOM geri yükleniyor, Effect'ler yeniden kuruluyor.

useEffectEvent hangi useEffect sorununu çözüyor?

Effect içindeki "olay benzeri" mantık bir değere bağımlıysa, o değer değiştiğinde tüm Effect gereksiz yere yeniden çalışıyordu (örneğin tema değişince sohbet odasının yeniden bağlanması). useEffectEvent, bu kısmı Effect'ten ayırıyor; dönen fonksiyon en güncel değerleri görüyor ama dependency array'e girmiyor.

cacheSignal Server Components'te ne yapar?

Render sırasında çağrıldığında bir AbortSignal döndürüyor; React render'ı bitirdiğinde, iptal ettiğinde veya hata aldığında bu sinyal abort ediliyor. cache() ile sarılmış fetch/DB çağrıları bu sinyali kullanarak artık gerekmeyen işlemleri iptal edebiliyor. Render dışında çağrılırsa null dönüyor.

React 19.2'ye geçerken nelere dikkat etmeliyim?

useEffectEvent için eslint-plugin-react-hooks'u @latest'e yükseltmen gerekiyor; aksi halde linter yanlış uyarılar üretebiliyor. Effect Event'ler yalnızca component/Hook üst seviyesinde tanımlanabiliyor ve yalnızca Effect'ler içinden çağrılabiliyor — linter bunu da doğruluyor.

Activity ile koşullu render arasındaki fark ne?

Koşullu render ({isVisible && <Page/>}) bileşeni tamamen unmount edip yeniden mount ediyor, state sıfırlanıyor. Activity ise hidden modda bileşeni DOM'da tutuyor (gizli), state'i koruyor, yalnızca Effect'leri temizliyor — geri dönüldüğünde state aynı yerden devam ediyor.

Güncelleme (Eylül 2026)

Bu makale yayınlandıktan sonra React 19.2 hattı bir üst sürüme devretti: React 19.3.0, 9 Eylül 2026'da react.dev üzerinden duyuruldu ve npm'de react paketinin latest dist-tag'i artık 19.3.0'ı gösteriyor. Bu makalenin yayın tarihi (5 Ağustos 2026) itibarıyla "19.2 hattı hâlâ aktif bakım alıyor" ve "en son patch 19.2.8" tespitleri o tarih için doğruydu; bugün itibarıyla ise en güncel hat React 19.3. Bu yazıda anlatılan Activity, useEffectEvent ve cacheSignal API'leri 19.3'te de aynı şekilde kullanılabilir durumda — 19.3 bu üç API'yi kaldırmıyor. Sürümün değişiklik listesinde <Activity> ve useEffectEvent için hata düzeltmeleri yer alıyor: "Fix useSyncExternalStore missing store mutations that happened while an <Activity> tree was hidden" (#36947), "Don't let errors escape a hidden <Activity>" (#35074) ve "Fix useEffectEvent to read the latest values in forwardRef and memo components" (#34831); ayrıca <Activity> artık Flight'ta (Server Components) destekleniyor (#34697). Kaynak: react.dev/blog/2026/09/09/react-19-3.

Sonuç

React 19.2'nin üç API'si birbirinden bağımsız ama tamamlayıcı problemleri çözüyor: Activity görünürlük ve state koruma arasındaki dengeyi, useEffectEvent Effect'lerdeki reaktif/olay ayrımını, cacheSignal ise sunucu render'ının iptal yaşam döngüsünü ele alıyor. Concurrency ve state yönetimi tarafında benzer prensipleri Swift dünyasında görmek istersen Swift Observation Framework: @Observable ile Modern State Management veya Swift Structured Concurrency Deep Dive yazılarına bakabilirsin. Cross-platform tarafta React ekosistemiyle daha yakından ilgileniyorsan React Native New Architecture 2026: Fabric, TurboModules ve Bridgeless Mode yazısı tamamlayıcı olacaktır. Bağımlılık/effect yönetimi konusundaki disiplinin Swift tarafındaki karşılığı için Async/Await Best Practices: Swift Concurrency Mastery yazısını, render optimizasyonu/state-preserving pattern'lerin Android tarafındaki karşılığı için Jetpack Compose 1.7 Performance: Strong Skipping + Stability yazısını inceleyebilirsin.

Kaynaklar

Etiketler

#React 19.2#Activity#useEffectEvent#cacheSignal#React Compiler#Server Components#Frontend
Muhittin Çamdalı

Muhittin Çamdalı

Lead Mobile Engineer

12+ yıllık deneyime sahip Lead Mobile Engineer. Swift, SwiftUI, Kotlin ve Flutter ile iOS, Android ve cross-platform mimarilerde uzman. Performanslı ve kullanıcı dostu mobil uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

İlgili İçerik