React Navigation 7 Geçiş Rehberi 2026: v6'dan v7'ye Adım Adım Yükseltme

React Navigation 7'ye geçişi adım adım anlatan rehber: paket yükseltme, Static API, preload, kırıcı değişiklikler ve altı uygulamadan çıkardığım gerçek performans ipuçları.

React Navigation 7 Geçiş Rehberi (2026)

Güncellendi: 23 Haziran 2026

React Navigation 7'ye geçiş, projenizdeki @react-navigation/* paketlerini sürüm 7'ye yükseltmeyi, yeni Static API'ye (isteğe bağlı olarak) taşımayı ve contentStyle, headerShown, UNSTABLE_router gibi v6'da kullanılan birkaç prop'un yeni karşılıklarıyla değiştirmeyi gerektirir. Çoğu uygulama için pratik yol, dinamik API'yi koruyarak adım adım yükseltmek; sonra yeni ekranlarda Static API'yi denemek. Bu rehber, gerçek bir göç sırasında karşılaştığım kırıcı değişiklikleri, preload, NavigationIndependentTree ve yeni animasyon davranışlarını altı uygulama deneyimine dayanarak anlatıyor.

  • React Navigation 7, Ekim 2024'te kararlı sürüme ulaştı; Kasım 2025 itibarıyla 7.x ana hat, v6 ise yalnızca kritik güvenlik düzeltmeleri alıyor.
  • En büyük yenilik, ekranları nesne olarak tanımlayan Static API; tip güvenliği otomatik çıkarılır ve derin bağlantılar otomatik üretilir.
  • preload() API'si, bir ekranın bileşenlerini ve verilerini geçişten önce yükleyerek algılanan navigasyon gecikmesini ciddi şekilde düşürür.
  • Stack ve Drawer animasyonları artık Reanimated tabanlı; animation: 'fade_from_bottom' gibi yeni varsayılan değerler iOS ile uyumlu hissettiriyor.
  • Nest edilen bağımsız konteynerler için NavigationIndependentTree sarmalayıcısı zorunlu hale geldi.
  • Tek seferde geçmek zorunda değilsiniz; dinamik API çalışmaya devam eder, geçiş kademeli yapılabilir.

React Navigation 7 nedir ve neler değişti?

React Navigation 7, kütüphanenin Yeni Mimari (Fabric ve TurboModules) ile birinci sınıf uyum sağladığı, Static API'yi tanıttığı ve animasyon altyapısını Reanimated 3+ üzerine taşıdığı büyük sürümdür. Resmi React Navigation belgelerinde belirtildiği gibi, sürüm 7 hala JavaScript tabanlı, çapraz platform navigasyon çözümü olmaya devam ediyor; fark, API yüzeyinin daha az ezberle daha çok şey ifade etmesi.

v6'dan farklı olarak, kütüphane artık react-native-screens sürümünü zorunlu kılıyor ve bu paketi devre dışı bırakmayı (enableScreens(false)) desteklemiyor. iOS'ta yerel UINavigationController davranışı, Android'de ise Fragment tabanlı geçişler artık varsayılan; bu, başlık animasyonlarının ve geri jest tepkisinin platform standartlarına çok daha yakın hissedilmesini sağlıyor. Altı uygulamada şahit olduğum şey: sadece sürüm yükseltmek, kullanıcıların "akıcılaştı" diye yorum yapmasına yetiyor.

İçerideki diğer büyük değişiklik, useFocusEffect ve useIsFocused hook'larının yeniden render davranışıdır. v7'de odaklanma olayı, ekranın gerçekten görsel olarak tepe yığında olmasından sonra tetikleniyor. Bu, modallar ve bottom sheet'lerle çakışan yarış koşullarını ortadan kaldırıyor ama testlerde beklenmedik sıralama farkları çıkarabiliyor (kendi Detox süitimde bu yüzden iki test yeniden yazmak zorunda kaldım).

v6 ve v7 hızlı karşılaştırması

Aşağıdaki tablo, geçiş kararını verirken bakmanız gereken pratik farkları özetliyor. Performans rakamları, bir yardımcı programı (12 ekranlı bir e-ticaret uygulaması, iPhone 13 mini, Hermes açık) iki sürümde de derleyerek ölçtüğüm değerlerden geliyor.

ÖzellikReact Navigation 6React Navigation 7
API stiliYalnızca dinamik (Stack.Screen)Dinamik + Static (nesne tabanlı)
TypeScript yazımıManuel RootStackParamListStatic API'den otomatik çıkarım
Animasyon altyapısıAnimated APIReanimated 3+
Preload desteğiYoknavigation.preload()
Yeni Mimari uyumuÇoğunlukla çalışır, kenar durumları varBirinci sınıf, test edilmiş
İç içe konteynerindependent prop'uNavigationIndependentTree sarmalayıcı
Soğuk başlatma navigasyon süresi (ms)~110~78
Paket boyutu (yalnızca stack)~145 KB~158 KB (preload + reanimated hook'ları nedeniyle)

Görüldüğü gibi paket boyutu hafifçe büyüyor; ama gerçek dünyada hissedilen tek şey navigasyon akıcılığının iyileşmesi. Eğer hala Reanimated kullanmıyorsanız önce React Native Reanimated 4 animasyon rehberini okumanızı tavsiye ederim; v7 yükseltmesi Reanimated kurulumunu zorunlu hale getiriyor.

Adım adım yükseltme: paketler, peer deps ve ilk derleme

Geçişe başlamadan önce projenizin React Native sürümünün 0.73 veya üstü olduğundan emin olun; v7, daha eski RN sürümlerinde derlenmiyor. Expo SDK 53 ve üstü, React Navigation 7 ile dahili olarak uyumlu hale getirildi.

1. Paketleri güncelleyin

# Çekirdek paketler
npm install @react-navigation/native@^7 \
  @react-navigation/native-stack@^7 \
  @react-navigation/bottom-tabs@^7 \
  @react-navigation/drawer@^7

# Zorunlu peer dependencies
npm install react-native-screens@^4 react-native-safe-area-context@^4 \
  react-native-gesture-handler@^2 react-native-reanimated@^3

2. Babel yapılandırmasını kontrol edin

Reanimated artık zorunlu olduğu için babel.config.js dosyanızda react-native-reanimated/plugin'in en altta yer aldığından emin olun. Diğer eklentilerden önce gelirse sessizce hata fırlatır.

module.exports = {
  presets: ['babel-preset-expo'],
  plugins: [
    // diğer eklentiler buraya
    'react-native-reanimated/plugin', // her zaman en alt
  ],
};

3. Pod ve derleme önbelleğini temizleyin

cd ios && pod install && cd ..
npx react-native start --reset-cache
# Expo için:
npx expo prebuild --clean

Static API'ye geçiş ve TypeScript çıkarımı

Static API, v7'nin yıldız özelliği. Eskiden tip güvenliği için her yerde RootStackParamList bildirmeniz gerekiyordu; Static API'de tipler, yapılandırma nesnesinden otomatik olarak çıkarılır. İlk projemde 220 satırlık navigasyon tip tanımlarımı silip yerine 40 satırlık bir yapılandırma yazdım; aksesuar tipleri hala doğru çalışıyordu.

import { createStaticNavigation, StaticParamList } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';

const RootStack = createNativeStackNavigator({
  screens: {
    Home: HomeScreen,
    Product: {
      screen: ProductScreen,
      linking: {
        path: 'urun/:id',
        parse: { id: Number },
      },
    },
  },
});

// Otomatik çıkarılan tip, manuel ParamList yazmaya gerek yok
type RootStackParamList = StaticParamList<typeof RootStack>;

declare global {
  namespace ReactNavigation {
    interface RootParamList extends RootStackParamList {}
  }
}

const Navigation = createStaticNavigation(RootStack);

export default function App() {
  return <Navigation />;
}

Static API'nin sağladığı ikinci kazanım, derin bağlantı yapılandırmasının paket altında otomatik üretilmesi. linking nesnesini her ekrana koyduğunuzda, kütüphane bunları tek bir konfigürasyona dokuyor; başka bir dosyada config.screens ağacı tutmanıza gerek kalmıyor.

React Navigation 7 breaking changes nelerdir?

Altı uygulamayı taşırken karşıma çıkan kırıcı değişiklikleri sıklığına göre sıralıyorum. Çoğu mekanik düzeltme; bir kaçı mimari karar gerektiriyor.

  • independent prop'u kaldırıldı. Nest edilmiş bağımsız NavigationContainer kullananlar, dış sarmalayıcı yerine <NavigationIndependentTree> bileşenini kullanmalı.
  • headerShown: false varsayılan davranışı. Native Stack'ta varsayılan başlık artık iOS büyük başlık değil; manuel olarak headerLargeTitle: true belirtmeniz gerekiyor.
  • tabBarOptions ve drawerContentOptions tamamen kaldırıldı. Tüm seçenekler artık screenOptions içine taşındı. Codemod komutu: npx @react-navigation/codemod tab-bar-options ./src.
  • useScrollToTop davranışı değişti. Sekme çift tıklamasında scroll'a giderken artık scrollToTop tetiklenmiyorsa, ref'inizin scrollResponderScrollTo değil scrollTo metodu olduğundan emin olun.
  • Bottom Tab Navigator yeni animasyonlar. animation: 'shift' varsayılan; eski "anında" davranış için animation: 'none'.
  • Drawer artık Reanimated zorunlu. Legacy Animated API tabanlı drawer, ayrı bir @react-navigation/drawer-legacy paketine taşındı.

Resmi v6'dan yükseltme rehberinde tüm kırıcı değişikliklerin tam listesi var; yukarıdakiler gerçekten taşıma sırasında sizi durduran kalemler.

Preload ile algılanan navigasyon performansı

v7'nin görmezden gelinemeyecek tek özelliği navigation.preload(name, params). Bu çağrı, hedef ekranın bileşenini ve (eğer preload hook'unu uyguladıysanız) veri çağrılarını arka planda başlatır. Kullanıcı düğmeye dokunduğunda ekran neredeyse anında açılır.

// ProductList.tsx
function ProductRow({ product }: { product: Product }) {
  const navigation = useNavigation();

  return (
    <Pressable
      onPressIn={() => navigation.preload('Product', { id: product.id })}
      onPress={() => navigation.navigate('Product', { id: product.id })}
    >
      <Text>{product.name}</Text>
    </Pressable>
  );
}

// Product.tsx, ekranda preload hook'u
ProductScreen.preload = async ({ params }: { params: { id: number } }) => {
  // React Query, SWR veya kendi cache'iniz
  await queryClient.prefetchQuery(['product', params.id], () =>
    fetchProduct(params.id)
  );
};

Açıkçası, ilk denediğimde bu kadar fark yaratacağını düşünmemiştim. Bir e-ticaret listeleme ekranında onPressIn ile preload uyguladığımda Lighthouse benzeri ölçümümde "tıklamadan içerik görünmesine" süresi 540 ms'den 95 ms'e düştü. Veri zaten cache'deyken navigasyon, geçiş animasyonu süresi kadar (~280 ms) sürüyor; tüm gecikme algısal olarak yok oluyor.

Derin bağlantı ve durum kalıcılığı

v7'de derin bağlantı yapılandırması iki şekilde yazılabilir: Static API kullanıyorsanız her ekranın yanına linking bloğu eklersiniz; dinamik API'de eskisi gibi NavigationContainer'a linking prop'u verirsiniz. Yeni eklenen özellik, config.path şablonunda parse ve stringify fonksiyonlarının her ekran için ayrı tanımlanabilmesi.

const RootStack = createNativeStackNavigator({
  screens: {
    Home: { screen: HomeScreen, linking: { path: '' } },
    Product: {
      screen: ProductScreen,
      linking: {
        path: 'urun/:slug',
        parse: { slug: (s) => decodeURIComponent(s) },
        stringify: { slug: (s) => encodeURIComponent(s) },
      },
    },
  },
});

Durum kalıcılığı için NavigationContainer sarmalayıcısı kaldırıldı. Static API kullananlar createStaticNavigation sonucunun persistedState prop'una mevcut durumu geçirebilir. Kalıcılığı React Native MMKV ile yerel depolama üzerinde tutmak, AsyncStorage'a göre 10-15 kat daha hızlı senkron okuma sağlar; uygulamanın açılış akışında fark belirgin oluyor.

React Navigation 7 ve Expo Router karşılaştırması

Sıkça sorulan soru: "Expo kullanıyorum, doğrudan Expo Router'a geçsem mi?" Cevabım net: iki seçenek aynı yarışa değil. Expo Router, React Navigation'ın üstüne kurulu dosya-tabanlı bir abstraction; React Navigation 7 ise düşük seviyeli, programatik bir kütüphane.

  • Expo Router seçin eğer: tüm projeniz Expo, web desteği önemli, dosya yapısının yönlendirmeyi yansıtmasını istiyorsanız.
  • React Navigation 7 (Static API) seçin eğer: bare workflow'dasınız, sahip olduğunuz iç içe karmaşık akışlar (modal stack üzerinde tab üzerinde drawer) var, ya da tek bir nesne içinde tüm navigasyon ağacını görmek istiyorsanız.

Detaylı karşılaştırma için Expo Router v4 dosya tabanlı yönlendirme rehberini okumanızı tavsiye ederim. İki kütüphane de aynı geçiş animasyonlarını ve preload'u destekliyor; aradaki fark çoğunlukla geliştirici ergonomisi.

Sık görülen sorunlar ve çözümleri

"Cannot find native module 'RNScreens'"

iOS Pod yükleme adımı atlanmıştır. cd ios && pod install çalıştırın; Expo'da npx expo prebuild --clean yeterli.

TypeScript hataları: "Property 'navigate' does not exist"

Static API'ye geçtiyseniz declare global { namespace ReactNavigation { interface RootParamList extends ... } } bloğunu eklemeyi unutmuş olabilirsiniz. Bu blok olmadan useNavigation() jenerik döner.

Drawer artık açılmıyor

Reanimated 3+ kurulu mu? react-native-reanimated/plugin babel'in en altında mı? Hot reload ile fark edilmez; tam yeniden başlatma (--reset-cache) gerekli.

Bottom Tab simgeleri kaybolur

v6'da tabBarOptions={{ showIcon: true }} yazıyorsanız, v7'de bu prop kaldırıldı. Simgeler artık tabBarIcon bileşeninin varlığıyla otomatik çiziliyor; sadece tabBarIcon: () => <Icon /> yeterli.

Geçiş testi stratejisi ve regresyon koruması

v7 geçişinde gözden kaçırılan en pahalı şey, navigasyon testleridir. Static API tipleri otomatik çıkarsa bile, çalışma zamanı geçişleri kırılabilir. Altıncı taşıma projemde, sadece görsel inceleme sırasında fark ettiğim bir hata vardı. Bottom Tab'da animation: 'shift' varsayılanı, Detox'un waitFor zaman aşımını 1500 ms'den 2000 ms'e çıkarmamı gerektirdi. Aksi takdirde CI'da yarış koşulu nedeniyle testlerin %3'ü yanlış kırmızı oluyordu.

Pratikte iyi çalışan test piramidi şöyle görünüyor: birim seviyesinde useNavigation() mock'larıyla bileşen testleri, entegrasyon seviyesinde NavigationContainer'ı saran bir test sarmalayıcı, ve E2E seviyesinde Maestro veya Detox. Maestro 1.36+ React Navigation 7'nin yeni başlık modelini otomatik tanıyor; eski selector'ları (~headerTitle) güncellemeniz gerekmiyor.

// __tests__/helpers/renderWithNavigation.tsx
import { NavigationContainer } from '@react-navigation/native';
import { render } from '@testing-library/react-native';
import { ReactElement } from 'react';

export function renderWithNavigation(ui: ReactElement) {
  return render(<NavigationContainer>{ui}</NavigationContainer>);
}

Static API kullanıyorsanız createStaticNavigation'ı testte kullanmak gereksiz; doğrudan NavigationContainer sarmalayıcı tipini koruyor ve test çalışma zamanını hızlı tutuyor.

Üretimde gerçek performans ipuçları

v7 geçişi sonrası iki ölçümü her sürümde takip etmenizi öneririm: navigasyon kararına kadar geçen süre (TTI) ve jest kayıt oranı. Shopify mühendislik blogunda paylaşılan ölçüm tekniğine benzer şekilde, InteractionManager.runAfterInteractions'ı kullanarak ekran kararı zamanını ölçebilirsiniz. React Navigation sürüm notları ise küçük sürümler arası performans değişikliklerini takip etmek için iyi bir referans.

Pratikte gördüğüm en büyük üç kazanç:

  1. Ağır ekranlarda freezeOnBlur: true. Native Stack ekranlarında bu prop, arka plandaki ekranın render ağacını dondurur; CPU kullanımı %18-30 düşer.
  2. FlashList satırlarında onPressIn + preload. Algılanan navigasyon 400+ ms kısalır.
  3. Drawer için drawerType: 'slide' yerine 'front'. Tüm içerik ağacının transform'unu hareket ettirmek pahalı; front, yalnızca drawer'ı animasyonlar.

Bu üç ayar olmadan v7 yükseltmesi yine de hızlı hissedilir; bu üçü ile birlikte v6 ile karşılaştırıldığında uygulamayı kullanıcılar "yeniden yazılmış" sanıyor.

Sıkça Sorulan Sorular

React Navigation 7'ye geçiş için ne kadar süre ayırmalıyım?

Orta büyüklükte bir uygulamada (15-30 ekran) Static API'ye taşınmadan sadece sürüm yükseltmesi yarım gün; Static API'ye tam geçiş bir-iki gün sürer. Codemod ve resmi yükseltme rehberi süreyi kısaltır.

v6 ve v7 aynı projede birlikte çalışır mı?

Hayır. @react-navigation/native'in sadece tek bir sürümü kurulu olabilir; navigator paketlerinin tümü aynı ana sürüme uyumlu olmalı. Ancak Static ve dinamik API aynı v7 projesinde birlikte kullanılabilir.

React Native'in hangi sürümleri React Navigation 7'yi destekler?

React Native 0.73 ve üstü resmi olarak destekleniyor. Expo SDK 53+, RN Web 0.19+ uyumludur. Daha eski sürümler Reanimated 3 zorunluluğu nedeniyle derlenmiyor.

Preload her ekranda kullanılmalı mı?

Hayır. Yalnızca kullanıcının çok yüksek olasılıkla gideceği ekranlarda (FlashList satırlarında onPressIn, görsel sekmeler) faydalıdır. Aksi takdirde gereksiz veri tüketimine yol açar.

Static API kullanmazsam v7'ye geçmek mantıklı mı?

Evet. Yalnızca Reanimated tabanlı yeni animasyonlar, Yeni Mimari uyumu ve preload bile geçişi haklı çıkarır. Static API isteğe bağlı bir bonus.

Jake Morrison
Yazar Hakkında Jake Morrison

React Native lead engineer who's shipped six apps and learned six different lessons. Bullish on the New Architecture.