İçeriğe geç
Muhammet Şafak
Günlük 3 dk okuma

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ı.


Looplio’nun mobil tarafını React Native ve Expo ile 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ışı.

// 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>
  );
}
// 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.

// 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.

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.

Etiketler: #React Native
Paylaş:

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi