Перейти к основному содержимому

Роутинг (Expo Router)

Приложение использует Expo Router v6 — file-based routing для React Native.

Структура маршрутов

app/
├── _layout.tsx # Root layout (providers)
├── +not-found.tsx # 404 fallback

├── (auth)/ # Группа: auth экраны
│ ├── _layout.tsx # Auth layout (AuthLayout)
│ ├── login.tsx
│ ├── register.tsx
│ ├── forgot-password.tsx
│ └── callback.tsx # OAuth callback

├── (onboarding)/ # Группа: первый запуск
│ ├── _layout.tsx
│ └── index.tsx

└── (app)/ # Группа: основное приложение
├── _layout.tsx

├── (tabs)/ # Bottom tab navigation
│ ├── _layout.tsx # Tab bar config
│ ├── index.tsx # Courses (главная)
│ ├── games.tsx # Games
│ └── profile.tsx # Profile

├── course/[id].tsx # Динамический: детали курса
├── lesson/[id].tsx # Динамический: просмотр урока

├── games/
│ ├── memory-cards.tsx
│ ├── pattern-sequence.tsx
│ ├── learning-style.tsx
│ ├── flashcards.tsx
│ └── typing.tsx

├── settings/
│ ├── index.tsx
│ ├── theme.tsx
│ ├── language.tsx
│ ├── notifications.tsx
│ └── subscription.tsx

└── subscription/
├── index.tsx # Paywall
└── success.tsx # После покупки

Группы маршрутов

Папки в круглых скобках (folder) — это группы. Они не влияют на URL, но позволяют:

  • Применять общий layout
  • Условно показывать/скрывать экраны
  • Логически группировать маршруты

Пример: auth vs app

// app/_layout.tsx
export default function RootLayout() {
const { session, isLoading } = useSession();

if (isLoading) return <SplashScreen />;

return (
<Stack screenOptions={{ headerShown: false }}>
{session ? (
<Stack.Screen name="(app)" />
) : (
<Stack.Screen name="(auth)" />
)}
</Stack>
);
}

Динамические маршруты

Файлы с [param] — динамические:

// app/(app)/course/[id].tsx
import { useLocalSearchParams } from 'expo-router';

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

// id = "123" для URL /course/123
}

Навигация

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

// Программная навигация
router.push('/course/123');
router.replace('/login');
router.back();

// Декларативная
<Link href="/course/123">
<Text>Открыть курс</Text>
</Link>

Tab Navigator

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

export default function TabsLayout() {
return (
<Tabs>
<Tabs.Screen
name="index"
options={{
title: 'Курсы',
tabBarIcon: ({ color }) => (
<Ionicons name="book" size={24} color={color} />
),
}}
/>
<Tabs.Screen
name="games"
options={{
title: 'Игры',
tabBarIcon: ({ color }) => (
<Ionicons name="game-controller" size={24} color={color} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Профиль',
tabBarIcon: ({ color }) => (
<Ionicons name="person" size={24} color={color} />
),
}}
/>
</Tabs>
);
}

Deep Linking

Expo Router автоматически поддерживает deep links. URL структура:

edu-mobile://course/123
edu-mobile://lesson/456
edu-mobile://settings/theme