import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
export default function TabLayout() {
return (
<Tabs screenOptions={{ tabBarActiveTintColor: '#2563eb' }}>
<Tabs.Screen
name="index"
options={{
title: 'Acasă',
tabBarIcon: ({ color, focused }) => (
<Ionicons name={focused ? 'home' : 'home-outline'} size={24} color={color} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profil',
tabBarIcon: ({ color, focused }) => (
<Ionicons name={focused ? 'person' : 'person-outline'} size={24} color={color} />
),
}}
/>
</Tabs>
);
}Dacă ai o aplicație React Native cu navigare clasică și te gândești dacă merită efortul să treci pe Expo Router, răspunsul scurt e: depinde cât de mult te doare deep linking-ul. În rândurile de mai jos trecem prin diferențele practice, când merită migrarea și cum configurezi un setup nested (Tabs + Stack) fără să-ți prinzi urechile în fișiere _layout.tsx.
Când are sens să migrezi (și când e doar bătaie de cap)
La începutul anului am migrat o aplicație de comenzi cu vreo 45k MAU de la React Navigation 6 la Expo Router v3. Motivul principal a fost deep linking-ul: aveam vreo 250 de linii de cod doar pentru config-ul de linkingOptions, plin de regex-uri fragile pentru notificări push și campanii de marketing.
Cu Expo Router, fiind file-based routing similar cu Next.js, deep links merg din oficiu pe baza structurii de foldere. Ai economisit timp și debug infernal.
Totuși, există un trade-off clar. React Navigation clasic îți dă libertate totală asupra structurii de directoare — poți ține ecranul, componentele lui, hook-urile și testele în același folder features/checkout. La Expo Router, ești obligat să muți tot ce e ecran în folderul app/. Dacă proiectul e mare și ai o structură modulară bine pusă la punct, refactorizarea te va ține ocupat câteva zile bune.
Cum configurezi Tabs + Stack fără să ascunzi manual tab bar-ul
Cea mai frecventă problemă când treci pe Expo Router este afișarea unui ecran de detalii peste tab bar. În React Navigation băgai Tab Navigator-ul ca ecran într-un Stack părinte. În Expo Router folosim Route Groups (foldere denumite cu paranteze rotunde, care nu afectează URL-ul).
Structura curată arată cam așa:
app/
_layout.tsx -> Stack principal (Auth, Modal, App)
(tabs)/
_layout.tsx -> Configurația de Tabs
index.tsx -> Tab 1: Feed / Home
profile.tsx -> Tab 2: Profil
product/
[id].tsx -> Ecran de produs (Stack, se deschide peste Tabs)
În root layout (app/_layout.tsx), definești un <Stack> care conține grupul (tabs) cu header ascuns, plus orice alt ecran care trebuie să acopere ecranul complet (cum ar fi detaliile de produs sau modalele de checkout).
Verdictul din producție
Type safety-ul generat automat pentru parametri și rute este excelent. Nu mai scrii manual tipuri infernale de NativeStackScreenProps sau CompositeScreenProps de mână.
Pe scurt: dacă pornești un proiect nou, mergi direct pe Expo Router fără ezitare. La proiecte existente mari, migrează doar dacă ai cerințe serioase de universal links, web export sau dacă config-ul actual de navigare a devenit de nementenabil. Altfel, React Navigation 6 sau 7 își face treaba la fel de bine sub capotă, având în vedere că Expo Router este construit chiar peste el.
Voi ați făcut pasul spre file-based routing pe mobile sau preferați controlul explicit din cod?