# React Native'de gezinme (navigation) ve ekran mimarisi

> React Native Navigation Stack, Tab ve Drawer yapılarını Looplio bağlamında kurmanın pratik kararları ve ekran mimarisi yaklaşımı.

- Yayın: 2024-02-04
- Kategori: Günlük
- Etiketler: React Native
- Okuma süresi: 3 dk okuma
- Kaynak: https://www.muhammetsafak.com.tr/blog/react-native-de-gezinme-navigation-ve-ekran-mimarisi/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
Looplio'nun mobil tarafını [React Native ve Expo ile](/blog/react-native-ve-expo-ile-mobil-uygulamaya-ilk-adim) geliştirirken ilk gerçek kararla hızlı yüzleştim: navigation yapısı nasıl olacak? Web'de URL yönlendirmesi adına verilmiş onlarca karar birikimim vardı; mobil farklı bir zihniyeti gerektiriyordu.

React Native'de navigasyon için fiilî standart `react-navigation` kütüphanesidir. Alternatifler var ama ekosistem bu kütüphanenin etrafında şekillenmiş. Mesele "ne kullanayım" değil, "nasıl kurayım".

## Temel yapı taşları: Stack, Tab, Drawer

`react-navigation` üç ana navigator tipi üzerine kurulu:

**Stack Navigator:** Ekranlar birbirinin üstüne yığılır; geri tuşu bir üstteki ekrana döner. Mobil uygulamanın en doğal geri alma davranışı buradan gelir. Listeleme → detay → düzenleme gibi hiyerarşik akışlar için biçilmiş kaftan.

**Tab Navigator:** Alt sekmeler ya da üst sekmeler. Uygulamanın ana bölümleri — Looplio'da Takvim, Görevler, Ayarlar gibi — için kullanılır. Kullanıcı bağlamı tamamen değiştirdiğinde, yığını terk edip ayrı bir sekmeye geçtiğinde.

**Drawer Navigator:** Yan menü. Tablet uygulamalarında ya da çok sayıda üst düzey bölümü olan uygulamalarda daha yaygın. Küçük telefon ekranlarında alt sekmeyi doldurma için zorlama yapmak yerine Drawer seçilebilir.

Gerçek uygulamalar bunları iç içe kullanır. Looplio'da dış katmanda bir Tab Navigator var; her sekme kendi Stack Navigator'ını barındırıyor. Bu sayede "Takvim" sekmesine geçtiğimde, son bıraktığım takvim görünümüne dönüyorum — web'deki URL geçmişine yakın bir hafıza davranışı.

```tsx
// App.tsx — basitleştirilmiş yapı
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { CalendarStack } from "./navigation/CalendarStack";
import { TaskStack } from "./navigation/TaskStack";
import { SettingsStack } from "./navigation/SettingsStack";

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Calendar" component={CalendarStack} />
        <Tab.Screen name="Tasks" component={TaskStack} />
        <Tab.Screen name="Settings" component={SettingsStack} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}
```

```tsx
// navigation/CalendarStack.tsx
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { CalendarScreen } from "../screens/CalendarScreen";
import { EventDetailScreen } from "../screens/EventDetailScreen";

const Stack = createNativeStackNavigator();

export function CalendarStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="CalendarHome" component={CalendarScreen} />
      <Stack.Screen name="EventDetail" component={EventDetailScreen} />
    </Stack.Navigator>
  );
}
```

## Ekran bileşenlerinin mimarisi

Navigation kurulumundan sonra gelen ikinci soru: screen'leri nasıl organize edeyim?

Mobil'de her ekran bileşeni doğası gereği biraz daha şişmeye meyillidir. Web'de bir sayfa genellikle birkaç bileşenden oluşur; mobil'de ise ekran; layout, veri çekme, yerel durum ve kullanıcı etkileşimi gibi her şeyi bir arada taşımak zorundaymış gibi görünür. Bu yanılsamaya direnmek önemli.

Ben şu ayrımı benimsedim: **Screen** koordinasyon yapar; veriyi çeker, durumu yönetir, alt component'lere iletir. **Saf component'ler** ise yalnızca prop alır ve görüntüler. Screen'i bir sayfa controller'ı gibi düşünüyorum.

```
screens/
  CalendarScreen.tsx    → veri çekme + durum
  EventDetailScreen.tsx → tek bir event'in detayı
components/
  EventCard.tsx         → bir etkinliği gösterir, hiçbir şey bilmez
  DayColumn.tsx         → takvim günü görünümü
```

Bu ayrım test edilebilirliği de artırıyor: `EventCard` saf bir bileşense, davranışını prop'larla kontrol edebiliyorsunuz.

## Ekranlar arası parametre aktarımı

Yığın içinde ekranlar arası veri aktarımında `route.params` kullanılır. Basit ID'ler için sorunsuz; ancak karmaşık nesne geçirmekten kaçınmak gerekir. Bir event detayına giderken tüm event objesini değil, yalnızca `eventId`'yi geçirmek ve detay ekranında API'den tekrar çekmek daha güvenli bir yol.

```tsx
// CalendarScreen'den EventDetail'e geçiş
navigation.navigate("EventDetail", { eventId: event.id });

// EventDetailScreen içinde
const { eventId } = route.params;
const { data: event } = useEvent(eventId);
```

Bu yaklaşım biraz ek ağ isteği getirir; ancak ekranın kendi veri doğruluğunu garanti etmesini sağlar. Özellikle takvim ekranından geçirilen verinin, kullanıcı detay ekranındayken arka planda değişme ihtimaline karşı güvenlidir.

## TypeScript ile tip güvenli navigasyon

`react-navigation` TypeScript desteği iyi; her gezgin için rota parametre tipleri tanımlanabiliyor. Bu, `route.params.eventId` gibi erişimlerde derleme zamanı güvencesi sağlıyor.

```tsx
type CalendarStackParamList = {
  CalendarHome: undefined;
  EventDetail: { eventId: string };
};
```

Bu tanımlamayı yapmak biraz başlangıç yatırımı istiyor ama ilerleyen haftalarda hata ayıklama süresi olarak geri kazandırıyor. Parametre adı değiştiğinde tüm kullanım yerlerini TypeScript buluyor.

## Gezinme yapısı kararı: önceden düşünün

Navigasyon yapısını sonradan değiştirmek maliyetlidir. Sekme sayısı, hangi ekranların aynı yığında olduğu, hangi ekranların modal olarak açılması gerektiği — bunlar uygulamanın kullanıcı deneyimini şekillendiren kararlar.

Looplio'yu kurarken önce kağıda bir kullanıcı akışı çizdim: kullanıcı ne görmek istiyor, nereye geçmek istiyor, "geri" tuşuna bastığında ne olmasını bekliyor? Bu soruların cevapları navigasyon yapısını belirledi; kod bunun ardından geldi.

Bu sırayı atlamamanızı öneririm.
