Expo Router v4: Fájl-alapú navigáció React Native-ban (2026)

Gyakorlati útmutató az Expo Router v4-hez: fájl-alapú útvonalak, Stack/Tabs/Drawer layoutok, Typed Routes, API útvonalak, deep linking és migráció React Navigationről.

Expo Router v4 Fájl-alapú Útmutató 2026

Frissítve: 2026. május 25.

Az Expo Router v4 egy fájl-alapú navigációs könyvtár React Native-hoz, amely a Next.js App Router mintájára az app/ mappa struktúrájából automatikusan generál típusbiztos útvonalakat iOS-re, Androidra és webre egyaránt. A 2026-os v4 kiadás natívan támogatja a React Server Componentset, az API útvonalakat és a megosztott elem-átmeneteket, miközben az alatta futó React Navigation v7 motorra épül. Ebben az útmutatóban végigvezetlek a beállításon, a tipikus mintákon és néhány buktatón, amit én is megtapasztaltam élesben.

  • Az Expo Router v4 az app/ könyvtárban található fájlokat automatikusan navigációs útvonalakká alakítja, csökkentve a boilerplate kódot.
  • A Typed Routes funkció TypeScript típusokat generál minden útvonalhoz, így a router.push() hívások fordítási időben ellenőrzöttek.
  • A v4 natívan támogatja a React Server Componentseket és az API útvonalakat (+api.ts), így a backend logika ugyanabban a projektben élhet.
  • Univerzális alkalmazásokat hoz létre: ugyanaz a kód fut iOS-en, Androidon és böngészőben, megosztott deep linking konfigurációval.
  • A React Navigation v7-re épül, ezért a Stack, Tabs és Drawer navigátorok minden lehetősége elérhető layout fájlokon keresztül.

Mi az Expo Router és miért érdemes használni?

Az Expo Router a Meta React Native csapatának és az Expo-nak közös válasza arra, hogy a hagyományos imperatív navigáció (manuálisan regisztrált Stack.Screen-ek) skálázhatatlanná válik közepes és nagyobb projektekben. A v4 megjelenésével (2026 januárjában) az Expo csapat egyértelművé tette, hogy ez a hivatalosan ajánlott megoldás minden új projekthez. A fájl-alapú megközelítés ismerős lehet azoknak, akik Next.js-szel vagy SvelteKittel dolgoztak: a fájlrendszer struktúrája egyben az URL struktúra is.

A legfontosabb előnye, hogy univerzális. Ugyanaz az app/profile.tsx fájl elérhető /profile URL-en a weben, és a megfelelő képernyőként natív alkalmazásban is. Ez különösen értékes, ha a marketing oldal és az alkalmazás egy közös kódbázisban él. Emellett a router automatikusan kezeli a deep linkinget, a böngésző history-t, és a 404-es hibákat egy beépített +not-found.tsx fájllal.

A v4 új funkciói közé tartozik a Server Components támogatás (kísérleti, de stabilizáció felé tart), a protected routes deklaratív definiálása layout szinten, valamint a shared element transitions a Reanimated 4-gyel együttműködve. Aki Reanimated animációkkal dolgozik, érdemes megnéznie a Reanimated 4 útmutatónkat, hiszen a router és az animációs réteg szorosan integrálódik.

Telepítés és projekt beállítása

Új projekt esetén a leggyorsabb út a hivatalos sablon használata, amely már tartalmazza az Expo Router v4 alapkonfigurációját. Meglévő Expo projekthez (SDK 55+) néhány csomag telepítésével és apró konfigurációs változtatásokkal hozzáadható.

# Új projekt létrehozása Expo Router sablonnal
npx create-expo-app@latest my-app --template tabs

# Vagy meglévő SDK 55+ projekthez hozzáadás
npx expo install expo-router react-native-screens react-native-safe-area-context
npx expo install expo-linking expo-constants expo-status-bar

A package.json belépési pontját módosítsd "main": "expo-router/entry" értékre, így az Expo Router veszi át a gyökér komponens betöltését. Az app.json-ban add hozzá a scheme mezőt (pl. "scheme": "myapp"), különben a deep linking nem fog működni iOS-en. Webes támogatáshoz a web.bundler értékét állítsd "metro"-ra, ami egyébként a v4-ben már alapértelmezett.

Egy gyors megjegyzés a saját tapasztalatból: az utolsó projektemben pont az app.json scheme-jét hagytam ki, és napokig kerestem, miért nem nyit meg semmit a deep link iOS-en. Onnantól mindig ez az első, amit ellenőrzök.

A projekt struktúrája ezután így néz ki: gyökérben az app/ mappa, benne _layout.tsx (a gyökér layout), index.tsx (a kezdő képernyő) és tetszőleges almappák. Minden más fájl (komponensek, hookok) maradjon a hagyományos src/ vagy components/ mappákban, hiszen csak az app/ tartalma generál útvonalakat.

Hogyan működnek a fájl-alapú útvonalak?

A fájl-alapú routing logikája egyszerű: minden .tsx vagy .jsx fájl az app/ mappában egy elérhető URL-t jelent. Az app/index.tsx a / útvonalra mappel, az app/settings.tsx a /settings-re, az app/profile/edit.tsx pedig a /profile/edit-re. A mappa nevek alapértelmezetten az URL szegmensek lesznek.

app/
├── _layout.tsx          → gyökér layout (minden képernyőre)
├── index.tsx            → /
├── settings.tsx         → /settings
├── profile/
│   ├── _layout.tsx      → /profile/* layout
│   ├── index.tsx        → /profile
│   └── edit.tsx         → /profile/edit
├── (tabs)/              → "group" (nem jelenik meg az URL-ben)
│   ├── _layout.tsx
│   ├── home.tsx         → /home
│   └── feed.tsx         → /feed
└── +not-found.tsx       → 404-es képernyő

A zárójeles mappák, mint a (tabs), úgynevezett route groupok: nem jelennek meg az URL-ben, csak logikailag csoportosítják a fájlokat (például egy tab navigátoron belüli képernyőket). Ez lehetővé teszi, hogy egy alkalmazás bejelentkezett ((app)) és nem bejelentkezett ((auth)) szekciói külön layouttal rendelkezzenek, de azonos URL gyökerükkel.

A + előtagú fájlok speciálisak: +not-found.tsx a 404-es kezelő, +html.tsx a webes HTML burok testreszabására, +api.ts pedig a szerver-oldali API útvonalakhoz (lásd alább).

Layoutok beállítása Stack, Tabs és Drawer navigátorokkal

A layout fájlok (_layout.tsx) határozzák meg, milyen navigátor (Stack, Tabs, Drawer) használja az adott mappa képernyőit. Egy gyökér Stack és egy beágyazott Tabs kombináció a leggyakoribb minta.

// app/_layout.tsx (gyökér Stack)
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <Stack screenOptions={{ headerStyle: { backgroundColor: '#0a7ea4' } }}>
      <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
      <Stack.Screen name="modal" options={{ presentation: 'modal' }} />
    </Stack>
  );
}

// app/(tabs)/_layout.tsx (beágyazott Tabs)
import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';

export default function TabLayout() {
  return (
    <Tabs screenOptions={{ tabBarActiveTintColor: '#0a7ea4' }}>
      <Tabs.Screen
        name="home"
        options={{
          title: 'Kezdőlap',
          tabBarIcon: ({ color }) => <Ionicons name="home" size={24} color={color} />,
        }}
      />
      <Tabs.Screen
        name="feed"
        options={{ title: 'Hírfolyam', tabBarIcon: ({ color }) => <Ionicons name="list" size={24} color={color} /> }}
      />
    </Tabs>
  );
}

A Drawer navigátorhoz külön kell telepítened a @react-navigation/drawer csomagot, és a react-native-gesture-handler wrapperrel kell körbevenni az alkalmazást. A layout fájlok deklaratívak, ezért az opciók (header címek, ikonok, animációk) ugyanúgy adhatóak meg, mint a klasszikus React Navigationben. Csak a regisztráció történik automatikusan a fájlszerkezet alapján.

Hogyan készíthetek dinamikus útvonalakat Expo Routerben?

A dinamikus útvonalakat szögletes zárójeles fájlnevekkel hozhatod létre: app/post/[id].tsx a /post/123, /post/abc stb. URL-ekre fog illeszkedni. A paramétert a useLocalSearchParams hookkal éred el.

// app/post/[id].tsx
import { useLocalSearchParams, Stack } from 'expo-router';
import { Text, View } from 'react-native';

export default function PostScreen() {
  const { id } = useLocalSearchParams<{ id: string }>();

  return (
    <View style={{ padding: 16 }}>
      <Stack.Screen options={{ title: `Bejegyzés #${id}` }} />
      <Text>A bejegyzés azonosítója: {id}</Text>
    </View>
  );
}

Több szegmensre illeszkedő útvonalakhoz a catch-all szintaxis használható: az app/docs/[...slug].tsx illeszkedik a /docs/intro, /docs/api/auth és bármilyen mély útvonalra. A slug paraméter ekkor egy string tömb lesz. Opcionális catch-all változat is létezik, dupla szögletes zárójellel ([[...slug]].tsx), ami a gyökér útvonalra is illeszkedik.

Navigáláshoz a router.push('/post/123') vagy a deklaratív <Link href="/post/123"> komponens használható. A v4-ben a Link komponens támogatja az asChild prop-ot, így bármilyen érintést kezelő komponenst átalakíthatsz navigációs linkké.

Typed Routes: TypeScript-biztos navigáció

Az egyik legnagyobb újdonság a v4-ben a Typed Routes stabilizációja. A funkciót az app.json-ban engedélyezheted ("experiments": { "typedRoutes": true }), és onnantól automatikusan generálódik egy .expo/types/router.d.ts fájl, amely tartalmaz minden valós útvonalat a projektedben. Innentől a TypeScript fordító elkapja az elgépelt URL-eket.

import { router, Link } from 'expo-router';

// Helyes (létező útvonal)
router.push('/profile/edit');
<Link href="/post/[id]" params={{ id: '42' }} />

// Fordítási hiba (nincs ilyen útvonal)
router.push('/profile/delte'); // elgépelés
<Link href="/post/[wrongParam]" />

Őszintén, ez a funkció önmagában megéri a v4-re váltást, ha TypeScripttel dolgozol. A szigorú móddal (strict: true) együtt szinte teljesen kizárja a navigációs hibákat. Ha állapotkezelést is használsz, érdemes átolvasni a Zustand és TanStack Query útmutatónkat, hogy az útvonalakhoz tartozó adatlekérés is típusbiztos legyen. A v4-ben a useLocalSearchParams visszatérési típusa automatikusan a dinamikus szegmensek nevéből származik, ha a typedRoutes engedélyezve van.

API útvonalak és szerver oldali logika

Az Expo Router v4 egyik leglátványosabb újdonsága az API Routes támogatás. A +api.ts végződésű fájlok szerver-oldali végpontokat hoznak létre, amelyeket EAS Hostingra vagy bármilyen Node.js-kompatibilis platformra deploy-olhatsz. A szintaxis a Next.js Route Handlers mintáját követi.

// app/users/[id]+api.ts
export async function GET(request: Request, { id }: Record<string, string>) {
  const user = await db.users.findUnique({ where: { id } });
  if (!user) {
    return new Response('Nem található', { status: 404 });
  }
  return Response.json(user);
}

export async function DELETE(request: Request, { id }: Record<string, string>) {
  await db.users.delete({ where: { id } });
  return new Response(null, { status: 204 });
}

Kliens oldalon ezeket az útvonalakat egyszerű fetch('/users/123') hívásokkal éred el. Az Expo Router automatikusan a megfelelő bázis URL-re irányítja a kéréseket fejlesztés és éles környezet között. Ez különösen praktikus, ha könnyű backend logikára van szükséged (autentikáció proxy, webhook fogadás, AI prompt sandbox), és nincs kedved külön szervert fenntartani hozzá. A részleteket az Expo API Routes dokumentációja tartalmazza.

Deep linking és univerzális linkek beállítása

A deep linking gyakorlatilag ingyenes az Expo Router használatakor: az app.json-ban definiált scheme alapján minden URL automatikusan a megfelelő képernyőre vezet. A myapp://post/123 URL pontosan ugyanúgy nyitja meg az alkalmazást, mint a https://example.com/post/123 webes változat.

Universal Links (iOS) és App Links (Android) beállításához az app.json-ban add hozzá az associatedDomains és intentFilters konfigurációt, majd helyezz el egy apple-app-site-association és egy assetlinks.json fájlt a tartomány gyökérkönyvtárában. Az Expo dokumentációja részletes példákat tartalmaz a deep linking guide oldalon. A v4-ben a Linking.createURL() automatikusan beilleszti az aktuális hoszt nevet és a sémát, így a megosztási linkek minden platformon működnek. Aki a háttérben futó React Native Linking API működésére is kíváncsi, ott találja a low-level részleteket.

Migráció a klasszikus React Navigationről

Sok meglévő projekt még a hagyományos imperatív React Navigation konfigurációt használja. A migráció a v4-re fokozatosan elvégezhető. Az első lépés az expo-router telepítése és a main belépési pont átállítása. Ezután a meglévő NavigationContainer és a benne lévő navigátorok egy az egyben átmozgathatók az app/_layout.tsx fájlba, mivel a Stack, Tabs és Drawer komponensek API-ja azonos a React Navigation v7 megfelelőivel.

A képernyőket egyenként mozgasd át az app/ mappa megfelelő helyére. A navigation.navigate('Profile', { id: 42 }) hívásokat cseréld router.push({ pathname: '/profile/[id]', params: { id: '42' } })-re. A useRoute() hook helyett a useLocalSearchParams()-t használd. A teljes migrációs útmutatót az Expo hivatalos migrációs dokumentációja írja le.

Egy átlagos közepes projektben (15–30 képernyő) a teljes migráció 1–2 fejlesztői napot vesz igénybe, és a fő haszon a redukált boilerplate (jellemzően 30–40%-kal kevesebb navigációs kód) és a típusbiztos linkek. Nálam egy 22 képernyős projektnél másfél nap volt, és a legtöbb idő a régi useNavigation() hívások cseréje volt.

Gyakori hibák és teljesítmény tippek

A leggyakoribb hibák jellemzően a layout fájlok hierarchiájával kapcsolatosak. Ha egy beágyazott navigátor (pl. Tabs) headerje és a szülő Stack headerje is megjelenik, az általában azt jelenti, hogy elfelejtetted beállítani a headerShown: false opciót a szülő Stack megfelelő képernyőjén. Egy másik gyakori csapda a route groupok félreértése: a (tabs) mappa nem jelenik meg az URL-ben, ezért az app/(tabs)/home.tsx útvonala /home, nem /tabs/home.

Teljesítmény szempontjából a v4 nagy előnye, hogy a képernyőket csak akkor tölti be, amikor először látogatják őket (lazy loading), így a kezdeti bundle méret jelentősen kisebb lehet. A unstable_settings exportálásával vezérelheted az alapértelmezett képernyőt és az anchor pontot. Hosszú listáknál és komplex animációknál továbbra is érdemes a Hermes motort és az Új Architektúrát használni; ez utóbbiról bővebben olvashatsz az Expo SDK 55 és Új Architektúra útmutatónkban.

Gyakran Ismételt Kérdések

Az Expo Router jobb, mint a React Navigation?

Az Expo Router a React Navigationre épül, ezért nem helyettesíti, hanem egy magasabb absztrakciót ad fölé. Új projektekhez a fájl-alapú megközelítés ajánlott, mert kevesebb boilerplate-tel jár, automatikus deep linkinget és webes támogatást kínál, valamint típusbiztos. Régi, stabil projekteknél a klasszikus React Navigation továbbra is teljesen működőképes.

Támogatja az Expo Router a webes platformot?

Igen, az Expo Router teljes mértékben támogatja a React Native Webet. Ugyanaz az app/ mappa generál útvonalakat iOS-re, Androidra és böngészőre is. A webes verzió valódi URL-eket, böngésző history-t és SEO-barát szerver oldali renderelést is támogat a v4-től kezdve.

Milyen Expo SDK verzió szükséges az Expo Router v4-hez?

Az Expo Router v4 az Expo SDK 55 vagy újabb verziójával kompatibilis. React Native 0.79+ és React 19.2+ szükséges hozzá. A korábbi SDK verziókhoz a v3 vagy v2 használható, de új funkciók (API Routes, Server Components) csak a v4-ben érhetők el.

Hogyan védhetek le egy útvonalat hitelesítéssel?

A leggyakoribb minta egy (auth) és egy (app) route group használata. A gyökér _layout.tsx ellenőrzi a felhasználó bejelentkezési állapotát, és a Redirect komponenssel a megfelelő csoportba irányítja. A v4-ben deklaratív protected opció is létezik a layout szinten, ami egyszerűsíti ezt a mintát.

Át tudom alakítani a meglévő React Navigation projektemet fokozatosan?

Igen, a migráció fokozatosan elvégezhető. Először állítsd be az Expo Routert, mozgasd át a navigátorokat az app/_layout.tsx-be, majd képernyőről képernyőre alakítsd át az útvonalakat fájl-alapú szerkezetre. A két rendszer rövid ideig együtt is élhet, ha óvatosan választod szét a felelősségi köröket.

A Szerzőről Marcus Adeyemi

Marcus is a senior React Native engineer based in Berlin with twelve years in mobile, the last seven of them in JavaScript-driven cross-platform work. He spent three years at SoundCloud rewriting the listener app's playback queue and offline-download stack on top of TrackPlayer, and another two and a half years at Delivery Hero leading the rider app's reliability work across 30+ markets. He started out as a native iOS developer at a smaller agency shipping white-label banking apps, which still shows up in his writing whenever the topic turns to bridging Swift code or wrangling Xcode build settings. Most of his posts here cover Reanimated 3 and Gesture Handler internals, CodePush versus EAS Update tradeoffs, and the kind of Hermes crash reports that only show up in production. He occasionally speaks at React Native EU.