eduardweb.
Navigație & StateIntermediar#react-native#typescript#expo#expo-router#react-navigation

Expo Router vs React Navigation: când merită migrarea și cum legi tab-urile de stack

De Ioan Manole, 12 sept. 2026 · 15 vizualizări · 2 like-uri

Postat 12 sept. 2026
typescript
// app/_layout.tsx - Layout-ul radacina ce imbina tabs si full-screen stack
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <Stack screenOptions={{ headerShown: false }}>
      {/* Grupul de tab-uri - ascundem header-ul stack-ului */}
      <Stack.Screen name="(tabs)" />
      
      {/* Ecran de detalii care va acoperi complet bara de tab-uri */}
      <Stack.Screen 
        name="product/[id]" 
        options={{
          headerShown: true,
          headerTitle: 'Detalii Produs',
          headerBackTitle: 'Înapoi'
        }} 
      />
      
      {/* Modal care se deschide nativ peste tot */}
      <Stack.Screen 
        name="filter-modal" 
        options={{ presentation: 'modal' }} 
      />
    </Stack>
  );
}

Migrarea de la clasicul React Navigation la Expo Router nu este neapărat o plimbare în parc. Am făcut pasul ăsta anul trecut pe un proiect de livrări cu vreo 15k utilizatori activi lunar și ne-am lovit de câteva decizii de arhitectură care nu erau deloc evidente în documentație. Dacă ai deja un setup stabil și te bate gândul să rescrii navigarea, citește rândurile de mai jos înainte să dai npm i.

Când merită migrarea și unde apar problemele

Expo Router nu înlocuiește React Navigation, ci este un wrapper file-based peste el. Gândește-te la el exact ca la trecerea de la React Router la Next.js App Router.

Câștigi enorm la două capitole: deep linking și consistență pe web. Înainte, la React Navigation, dacă voiai deep links pentru campanii de marketing și push notifications, pierdeai lejer două zile scriind manual obiectul gigant de linking config și testând regex-uri pe Android și iOS. Cu Expo Router, structura de fișiere îți dă deep links automat. Funcționează pur și simplu.

Unde e buba? Trade-off-ul principal e rigiditatea. La React Navigation clasic erai obișnuit să pasezi componente, să faci randare condiționată direct în JSX (isAuth ? <AppStack /> : <AuthStack />) și să ai control absolut pe ciclul de viață al ecranelor. În Expo Router, totul trece prin layouts (_layout.tsx) și redirects declarative. Dacă logica ta de auth e complicată, te vei lupta puțin cu flash-uri de ecran până înveți să folosești corect sloturile și starea de hydration.

Pe scurt: merită dacă vrei universal app (web + mobile) sau ai multe deep links. Nu merită dacă ai o aplicație enterprise gigantică, scrisă acum 4 ani, care funcționează brici cu stack-uri imperative.

Cum legi corect un Tab Navigator de un Stack nested

Cea mai frecventă bătaie de cap este scenariul clasic: ai un ecran cu 3 tab-uri jos (Home, Search, Profile), dar când utilizatorul dă click pe un produs din Home, vrei ca ecranul de detalii să acopere tab bar-ul (să fie un stack pe tot ecranul, nu să rămână tab-urile vizibile dedesubt).

În React Navigation clasic făceai un Stack rădăcină care conținea TabNavigator ca prim ecran, urmat de ecranul Details. În Expo Router rezolvi asta prin grupuri de foldere: pui tab-urile într-un grup separat (tabs), iar rutele modale sau de detaliu full-screen le pui la același nivel cu grupul, în interiorul stack-ului rădăcină.

O greșeală comună pe care am pățit-o la început: am lăsat headerShown: true pe ambele niveluri și ne-am trezit cu două headere native suprapuse pe ecran. Stack-ul rădăcină trebuie să aibă grijă doar de tranziția paginii, în timp ce layout-ul intern din (tabs) gestionează tab bar-ul și propriile headere.

Auth flow: schimbarea de paradigmă

Nu mai poți schimba stack-ul dinamic la runtime bazat pe un boolean. În Expo Router verifici sesiunea într-un hook în rădăcină, iar layout-ul folosește componenta <Redirect href="/login" /> dacă userul nu e autentificat.

Aici am pierdut noi câteva ore bune: dacă pui Redirect înainte ca store-ul de auth (Zustand/Redux) să termine citirea din SecureStore, utilizatorul logat va vedea o secundă pagina de login. Asigură-te că ții montat un splash screen nativ (SplashScreen.preventAutoHideAsync()) până când știi sigur dacă token-ul există sau nu.

Tu ai făcut pasul spre Expo Router pe proiecte de producție sau rămâi la configurarea clasică declarativă?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.