Expo Router у React Native: Повний посібник з файлової навігації
Вивчіть Expo Router для React Native: файлова маршрутизація, макети, динамічні маршрути, типізована навігація та просунуті патерни, як модальні вікна та вкладки.

Expo Router впроваджує файлову маршрутизацію в React Native, замінюючи ручне налаштування навігації конвенційним підходом, натхненним Next.js. Починаючи з Expo SDK 57 та Expo Router, створення кросплатформної навігації для Android, iOS та веб зводиться до розміщення файлів у правильному каталозі.
Нові проєкти Expo постачаються з попередньо налаштованим Expo Router. Достатньо виконати npx create-expo-app@latest --template default, щоб розпочати роботу з файловою навігацією. Для існуючих проєктів необхідно встановити expo-router та оновити точку входу.
Як працює файлова маршрутизація в Expo Router
Кожен файл у каталозі app автоматично стає маршрутом. Шлях до файлу безпосередньо відповідає URL-шляху, усуваючи потребу в централізованому налаштуванні навігації. Файл app/settings.tsx створює маршрут /settings, а app/profile/edit.tsx відповідає маршруту /profile/edit.
Такий підхід пропонує три ключові переваги порівняно з традиційним налаштуванням React Navigation:
- Нульова конфігурація: маршрути з'являються в момент створення файлу
- Автоматичний deep linking: кожен екран отримує URL, що забезпечує можливість поширення та тестування
- Типізована навігація: TypeScript знає, які маршрути існують на етапі компіляції
import { View, Text, StyleSheet } from 'react-native'
import { Link } from 'expo-router'
export default function HomeScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Welcome</Text>
{/* Link maps directly to file path */}
<Link href="/settings" style={styles.link}>
Open Settings
</Link>
<Link href="/profile/edit" style={styles.link}>
Edit Profile
</Link>
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', padding: 24 },
title: { fontSize: 28, fontWeight: 'bold', marginBottom: 16 },
link: { fontSize: 16, color: '#61DAFB', marginTop: 12 },
})Компонент Link забезпечує навігацію на всіх платформах. У вебі він рендериться як тег <a> з відповідним атрибутом href для SEO. На нативних платформах він ініціює стекову навігацію.
Структура проєкту та файли макетів
Expo Router використовує файли _layout.tsx для визначення контейнерів навігації. Кожен каталог може мати власний макет, створюючи вкладені ієрархії навігації. Кореневий макет обгортає весь застосунок, тоді як вкладені макети контролюють окремі розділи.
Типова структура проєкту виглядає наступним чином:
app/
_layout.tsx # Root layout (Stack or custom)
index.tsx # Home screen (/)
(tabs)/ # Tab group (parentheses = route group)
_layout.tsx # Tab navigator
home.tsx # /home tab
search.tsx # /search tab
profile.tsx # /profile tab
settings/
_layout.tsx # Settings stack layout
index.tsx # /settings
notifications.tsx # /settings/notifications
privacy.tsx # /settings/privacyГрупи маршрутів — каталоги, загорнуті в дужки — організовують файли без впливу на URL. Каталог (tabs) вище створює навігатор вкладок, але URL-адреси залишаються у вигляді /home, /search та /profile, а не /tabs/home.
import { Stack } from 'expo-router'
export default function RootLayout() {
return (
<Stack
screenOptions={{
headerStyle: { backgroundColor: '#1a1a2e' },
headerTintColor: '#ffffff',
headerTitleStyle: { fontWeight: '600' },
}}
>
<Stack.Screen name="index" options={{ title: 'Home' }} />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="settings" options={{ title: 'Settings' }} />
</Stack>
)
}Кореневий макет також є місцем для завантаження шрифтів, ініціалізації провайдерів та налаштування глобальних параметрів.
Створення навігації вкладками з Expo Router
Навігація вкладками потребує файлу _layout.tsx всередині групи маршрутів. Expo Router надає як NativeTabs для платформоспецифічного досвіду вкладок, так і стандартний компонент Tabs для більшості випадків використання. Починаючи з SDK 56, Native Tabs підтримує властивість disabled, що дозволяє заблокувати вибір вкладки, зберігаючи її видимою.
import { Tabs } from 'expo-router'
import { Ionicons } from '@expo/vector-icons'
export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#61DAFB',
tabBarInactiveTintColor: '#888',
tabBarStyle: {
backgroundColor: '#1a1a2e',
borderTopColor: '#2d2d44',
},
}}
>
<Tabs.Screen
name="home"
options={{
title: 'Home',
tabBarIcon: ({ color, size }) => (
<Ionicons name="home" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="search"
options={{
title: 'Search',
tabBarIcon: ({ color, size }) => (
<Ionicons name="search" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profile',
tabBarIcon: ({ color, size }) => (
<Ionicons name="person" size={size} color={color} />
),
}}
/>
</Tabs>
)
}Кожен файл екрану вкладки експортує стандартний React-компонент. Іконка, мітка та значок панелі вкладок налаштовуються через властивість options у макеті.
Динамічні маршрути та параметри маршрутів
Динамічні сегменти використовують квадратні дужки в назві файлу. Файл із назвою [id].tsx відповідає будь-якому окремому сегменту, тоді як [...slug].tsx перехоплює всі наступні сегменти.
import { View, Text, StyleSheet } from 'react-native'
import { useLocalSearchParams, Stack } from 'expo-router'
export default function ProductScreen() {
// Extract the dynamic parameter from the URL
const { id } = useLocalSearchParams<{ id: string }>()
return (
<View style={styles.container}>
<Stack.Screen options={{ title: \`Product \${id}\` }} />
<Text style={styles.heading}>Product Details</Text>
<Text style={styles.id}>ID: {id}</Text>
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 24 },
heading: { fontSize: 24, fontWeight: 'bold', marginBottom: 8 },
id: { fontSize: 16, color: '#888' },
})При переході до /product/42 цей екран рендериться з параметром id, встановленим у "42". Хук useLocalSearchParams забезпечує типізований доступ до всіх параметрів маршруту.
Для маршрутів типу catch-all файл [...slug].tsx перехоплює цілі сегменти шляху:
import { useLocalSearchParams } from 'expo-router'
export default function DocsScreen() {
// /docs/getting-started/installation → slug = ['getting-started', 'installation']
const { slug } = useLocalSearchParams<{ slug: string[] }>()
return <DocViewer path={slug.join('/')} />
}Готовий до співбесід з React Native?
Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.
Типізовані маршрути для безпеки на етапі компіляції
Expo Router автоматично генерує типи маршрутів при увімкненій опції typed routes. Це дозволяє виявляти некоректні посилання на етапі компіляції, а не під час виконання.
Активація типізованих маршрутів у файлі app.json:
{
"expo": {
"experiments": {
"typedRoutes": true
}
}
}Після активації властивість href компонента Link та аргумент router.push() приймають лише валідні рядки маршрутів:
import { router } from 'expo-router'
function handleCheckout(cartId: string) {
// TypeScript validates this route exists
router.push(\`/product/\${cartId}\`)
// This would cause a compile error if /nonexistent doesn't exist
// router.push('/nonexistent')
}Типізовані маршрути ідеально поєднуються з useLocalSearchParams. Згенеровані типи гарантують відповідність імен параметрів між визначенням маршруту та компонентом, що його використовує, запобігаючи неочевидним помилкам, які проявляються лише при переході на конкретний екран.
Модальні екрани та параметри презентації
Модальні вікна в Expo Router — це звичайні екрани, налаштовані з параметром presentation: 'modal' у макеті. Такий підхід зберігає файлову конвенцію — модальне вікно є просто ще одним маршрутом.
import { Stack } from 'expo-router'
export default function RootLayout() {
return (
<Stack>
<Stack.Screen name="index" />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
{/* Modal screen slides up from the bottom */}
<Stack.Screen
name="create-post"
options={{
presentation: 'modal',
headerTitle: 'New Post',
}}
/>
</Stack>
)
}import { View, TextInput, Button, StyleSheet } from 'react-native'
import { router } from 'expo-router'
import { useState } from 'react'
export default function CreatePostModal() {
const [title, setTitle] = useState('')
const handleSubmit = () => {
// Submit logic here
router.back() // Dismiss the modal
}
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Post title"
value={title}
onChangeText={setTitle}
/>
<Button title="Publish" onPress={handleSubmit} />
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 24 },
input: {
borderWidth: 1,
borderColor: '#333',
borderRadius: 8,
padding: 12,
fontSize: 16,
marginBottom: 16,
},
})При переході до /create-post активується модальна презентація. Виклик router.back() закриває модальне вікно, повертаючись до попереднього екрану в стеку.
Програмна навігація та API маршрутизатора
Окрім компонента Link, Expo Router надає імперативний API через об'єкт router. Він обробляє навігацію, ініційовану бізнес-логікою, а не безпосередньою взаємодією користувача.
import { router } from 'expo-router'
// Push a new screen onto the stack
router.push('/profile/settings')
// Replace the current screen (no back button)
router.replace('/login')
// Go back to the previous screen
router.back()
// Navigate with parameters
router.push({
pathname: '/product/[id]',
params: { id: '42', source: 'recommendations' },
})
// Check if going back is possible
import { useRouter } from 'expo-router'
function BackButton() {
const router = useRouter()
return router.canGoBack() ? (
<Button title="Back" onPress={() => router.back()} />
) : null
}Різниця між router.push та router.replace має значення при потоках автентифікації в React Native. Після успішного входу router.replace('/dashboard') запобігає поверненню до екрану входу.
router.replace() замінює поточний запис в історії навігації. Для механізмів захисту, що перенаправляють неавтентифікованих користувачів, слід використовувати <Redirect href="/login" /> всередині рендеру компонента — він спрацьовує на етапі рендерингу та коректно працює з серверним рендерингом.
Middleware та захист маршрутів
Expo Router надає серверне middleware для логіки на рівні маршрутів. Файл +middleware.ts перехоплює запити до їх потрапляння до компонента маршруту, забезпечуючи перевірку автентифікації, перенаправлення та маніпуляцію заголовками.
import { type MiddlewareRequest } from 'expo-router/server'
export function middleware(request: MiddlewareRequest) {
const { pathname } = request.nextUrl
// Protect dashboard routes
const protectedPaths = ['/dashboard', '/settings', '/profile']
const isProtected = protectedPaths.some(p => pathname.startsWith(p))
if (isProtected) {
const token = request.cookies.get('session')
if (!token) {
return Response.redirect(new URL('/login', request.url))
}
}
return undefined // Continue to route
}На нативних платформах, де серверне middleware не працює, захист маршрутів спирається на клієнтські механізми. Поширений патерн полягає в обгортанні захищених макетів перевіркою автентифікації:
import { Redirect, Stack } from 'expo-router'
import { useAuth } from '@/hooks/useAuth'
export default function AuthenticatedLayout() {
const { isLoggedIn, isLoading } = useAuth()
if (isLoading) return null
if (!isLoggedIn) return <Redirect href="/login" />
return <Stack />
}Серверне middleware працює виключно у вебі з серверним рендерингом. Для нативних застосунків завжди слід реалізовувати клієнтський захист маршрутів у компонентах макетів. Поєднання обох підходів гарантує послідовний захист на всіх платформах.
Міграція SDK 56: Fork React Navigation
Починаючи з Expo SDK 56, Expo Router більше не залежить від пакетів @react-navigation/*. Якщо проєкт імпортує безпосередньо з React Navigation, необхідно оновити імпорти:
| Оригінальний пакет | Нове розташування |
|---|---|
@react-navigation/native | expo-router/react-navigation |
@react-navigation/stack | expo-router/js-stack |
@react-navigation/bottom-tabs | expo-router/js-tabs |
Codemod автоматично оновлює імпорти:
npx expo-codemod sdk-56-expo-router-react-navigation-replace srcAPI під час виконання залишається незмінним. Змінено лише специфікатори модулів. Сторонні бібліотеки, що досі імпортують з @react-navigation/core, працюють автоматично, оскільки Expo CLI переписує ці імпорти під час збірки.
Джерела
- Документація Expo Router — офіційний посібник та довідник API
- Expo SDK 57 Changelog — актуальні примітки до стабільного випуску
- Expo Router v56 Blog Post — пояснення форку React Navigation
- Посібник міграції SDK 55 до 56 — кроки міграції імпортів
Що очікують на співбесідах щодо Expo Router
- Expo Router автоматично перетворює кожен файл у каталозі
appна маршрут, усуваючи ручне налаштування навігації - Макети, визначені через файли
_layout.tsx, створюють ієрархії навігації для стеків, вкладок та бічних панелей - Динамічні маршрути з
[param].tsxта маршрути catch-all з[...slug].tsxзабезпечують параметризовану навігацію з повною підтримкою TypeScript - Типізовані маршрути виявляють некоректні навігаційні посилання на етапі компіляції після увімкнення в
app.json - Модальні екрани, програмна навігація через
router.push/replace/backта серверне middleware доповнюють інструментарій маршрутизації - Групи маршрутів із каталогами в дужках організовують код без впливу на URL-адреси
- Клієнтський захист маршрутів у макетах забезпечує автентифікацію на нативних платформах, а серверне middleware покриває веб
- Починаючи з SDK 56, імпорти з
@react-navigation/*мають бути оновлені до відповідниківexpo-router/*
Більше інформації про архітектуру React Native та підготовку до співбесід у модулі про нативні модулі.
Починай практикувати!
Перевір свої знання з нашими симуляторами співбесід та технічними тестами.
Чи знайдеш ти помилку в React Native?
Справжній фрагмент коду, прихована помилка, одна спроба на день. Щоб спробувати, акаунт не потрібен.

Автор:
Anthony Fillion-MailletЗасновник SharpSkill
Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.
Оновлено 6 жовтня 2026 р.
Теги
Поділитися
Пов'язані статті

Посібник з розробки додатків React Native 2026: Продакшн-застосунки та питання для співбесіди
Повний посібник з розробки продакшн-застосунків React Native у 2026 році, що охоплює Expo SDK 56, EAS Build, Hermes V1, Нову Архітектуру та підготовку до співбесід для розробників React Native.

Hermes V1 у React Native 0.84: Продуктивність, Прекомпільований Байткод та Питання на Співбесіді
Глибокий аналіз оптимізацій продуктивності Hermes V1 у React Native 0.84: прекомпіляція байткоду, збирач сміття Hades, керування пам'яттю та ключові питання на співбесіді для мобільних розробників.

React Native та TypeScript у 2026: Типобезпечна архітектура та питання співбесіди
Створення типобезпечних React Native додатків з TypeScript, Codegen, TurboModules та Strict TypeScript API. Охоплює патерни архітектури, типізовану навігацію, вимоги toolchain для 0.87 та питання співбесіди.