11 / 12
View Transition ve Activity
React 19.3'te kararlı hâle gelen ViewTransition ile animasyon ve Activity ile gizlenen ekranın state'ini korumak.
İki Yeni Bileşen
React 19.2 <Activity>'yi, React 19.3 de <ViewTransition>'ı kararlı hâle getirdi.12 İkisi de aynı soruya cevap verir: arayüz bir durumdan diğerine geçerken ne olmalı? ViewTransition geçişi canlandırır, Activity gizlenen parçanın state'ini korur.
ViewTransition
<ViewTransition>, tarayıcının View Transition API'sini React'e bağlar. Animasyon istediğiniz parçayı sarmanız yeterlidir:23
import { startTransition, useState, ViewTransition } from "react";
function SizeGuideToggle() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => startTransition(() => setIsOpen((open) => !open))}>
Beden tablosu
</button>
{isOpen && (
<ViewTransition>
<SizeGuide />
</ViewTransition>
)}
</>
);
}Uyarı
Animasyon yalnızca güncelleme bir Transition olduğunda çalışır: startTransition, bir Suspense boundary'nin açılması ya da useDeferredValue. Düz setState acildir ve animasyonsuz uygulanır.3 "Animasyon çalışmıyor" sorununun en sık sebebi budur.
React ağacın nasıl değiştiğine bakıp animasyonun türünü kendisi seçer:3
| Tür | Ne zaman |
|---|---|
enter | ViewTransition eklendiğinde |
exit | ViewTransition kaldırıldığında |
update | İçeriği ya da boyutu değiştiğinde |
share | Aynı name'e sahip biri kaldırılıp diğeri eklendiğinde |
Varsayılan animasyon tarayıcının cross-fade'idir. Özelleştirmek için türe bir View Transition Class verir, CSS'te view transition pseudo-elemanlarıyla stillersiniz:3
<ViewTransition enter="slide-up" exit="slide-down">
<CartDrawer />
</ViewTransition>::view-transition-new(.slide-up) {
animation: 250ms ease-out both slide-from-bottom;
}
::view-transition-old(.slide-down) {
animation: 200ms ease-in both slide-to-bottom;
}Birkaç kural:
Ortak eleman geçişi için
nameverin. Liste sayfasındaki ürün görseli ile detay sayfasındaki büyük görsel aynıname'i taşırsa React biri kaybolup diğeri gelirken görseli yerinden büyüterek taşır.nameuygulamada aynı anda tek olmalıdır;name={`product-${id}`}gibi bir önek kullanın. Diğer durumlarda isim vermeyin, React otomatik verir.3Yönü
addTransitionTypeile söyleyin. Galeride ileri ve geri aynı state'i değiştirir ama farklı yöne kaymalıdır; transition'a bir tür ekleyip class'ı türe göre seçersiniz.23enter/exityalnızca en üstte çalışır.ViewTransition'ın üstünde bir DOM elemanı varsa ekleme ve çıkarma animasyonu tetiklenmez.3startViewTransition'ı kendiniz çağırmayın. React çağırır ve başka bir View Transition'ı keser.3
Suspense ile
<ViewTransition> bir Suspense boundary'yi sardığında React iskeletten içeriğe geçişi canlandırır. 19.3 ile React, açılış animasyonundan önce görünür görselleri ve yeni fontları en fazla 500 ms bekler; içerik görseli yerinde açılır, metin yanlış fontla yanıp sönmez.24
<ViewTransition>
<Suspense fallback={<ProductSkeleton />}>
<ProductDetails id={id} />
</Suspense>
</ViewTransition>Erişilebilirlik
React, hareketi azaltmak isteyen kullanıcılar için animasyonları kendiliğinden kapatmaz. Dokümanın önerisi: her zaman prefers-reduced-motion ile kapatın ya da yumuşatın.3
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}Konunun ayrıntısı Renk, kontrast ve hareket dersinde.
Activity
<Activity> bir parçayı ekrandan kaldırmadan gizler. mode="hidden" olduğunda React çocukları display: none ile saklar ve Effect'lerini söker. visible'a dönünce state ve DOM olduğu gibi geri gelir, Effect'ler yeniden kurulur.5
import { Activity, useState } from "react";
function ProductTabs() {
const [tab, setTab] = useState<"details" | "reviews">("details");
return (
<>
<TabBar value={tab} onChange={setTab} />
<Activity mode={tab === "details" ? "visible" : "hidden"}>
<ProductDescription />
</Activity>
<Activity mode={tab === "reviews" ? "visible" : "hidden"}>
<ReviewList />
</Activity>
</>
);
}Koşullu render'dan farkı:
{isOpen && <Panel />} | <Activity mode> | |
|---|---|---|
| Gizlenince state | Silinir | Korunur |
| Gizlenince DOM | Silinir | display: none |
| Gizlenince Effect'ler | Söküldü | Söküldü |
| Yeniden açılış | Sıfırdan mount | Anında, kaldığı yerden |
Tipik kullanımlar: kullanıcının yazdığı yorum taslağı sekme değişince kaybolmasın, kapatılan kenar menüsü kaydırma konumunu hatırlasın. Ayrıca kullanıcının muhtemelen açacağı bir ekranı gizli modda önceden render edip verisini hazırlayabilirsiniz; gizli parça daha düşük öncelikle render edilir.56
İpucu
Gizlenen parçada video, ses ya da bir zamanlayıcı varsa Effect cleanup'ında durdurun. Activity Effect'leri söker ama <video> elemanı DOM'da kalır ve kendi kendine oynamaya devam edebilir.5
Kendin Dene
SizeGuideToggle'dastartTransition'ı kaldırın; animasyon ne oldu?CartDraweriçinslide-up/slide-downclass'larını ve@keyframes'leri yazın, sonra işletim sisteminizde "hareketi azalt" ayarını açıp deneyin.Ürün kartındaki görsel ile detaydaki görsele aynı
name'i verin ve sayfa geçişini izleyin.ProductTabs'ta yorum formuna bir şey yazın, sekmeyi değiştirip geri dönün. SonraActivityyerine&&kullanıp tekrar deneyin.
Detaylı Öğrenmek İçin
Resmi doküman:
<ViewTransition>referansı; ekleme/çıkarma, ortak eleman, liste sıralama, Suspense ve JavaScript ile animasyon örnekleri.3Video: Chance Strickland'ın React ekibiyle birlikte hazırladığı "View Transitions and Activity" konuşması (React Conf 2025, 1. gün).7
Resmi doküman: React Labs'in Nisan 2025 yazısı; iki özelliğin neden ve nasıl tasarlandığı.6
Kaynaklar
1 Ekim 2025. `<Activity>`'nin kararlı sürümü.
9 Eylül 2026. `<ViewTransition>`, `addTransitionType` ve Suspense ile görsel ve font bekleme.
Tetikleyiciler, View Transition Class, `name`, üst seviye kuralı ve `prefers-reduced-motion` notu.
ViewTransition varken görseller ve fontlar için 500 ms bekleme.
Gizli modda `display: none`, Effect'lerin sökülmesi, state'in korunması ve medya uyarısı.
23 Nisan 2025. İki özelliğin deneysel duyurusu ve tasarım gerekçesi.
: — 1. gün yayını. `<Activity>` ve `<ViewTransition>` ile doğal hissettiren animasyonlar.
Son güncelleme tarihi: 21 Ekim 2026
