Expo Router — fayllar asosidagi navigatsiya

~15 daq · React Native · Navigatsiya — Expo Router

Muammodan boshlaylik

Hozirgacha ilovamizda bitta ekran edi. Haqiqiy ilovada esa o'nlab: bosh sahifa, katalog, mahsulot, savat, profil, sozlamalar, kirish... Ular orasida o'tish, orqaga qaytish, parametr uzatish, tablar, modal oynalar kerak.

Vebda bu — URL va havolalar. Mobil ilovada URL yo'q... yoki bormi?

Expo Router — fayllar asosidagi navigatsiya: app/ papkasidagi har bir fayl — ekran, papka tuzilmasi — navigatsiya tuzilmasi. Next.js ni bilsangiz — juda tanish.


Fayl = ekran

app/
├── _layout.tsx           ← ildiz layout
├── index.tsx             ← /
├── katalog.tsx           ← /katalog
├── savat.tsx             ← /savat
└── mahsulot/
    └── [id].tsx          ← /mahsulot/42, /mahsulot/7 ...

Har bir faylda — export default komponent:

// app/katalog.tsx
import { View, Text } from 'react-native';

export default function Katalog() {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Katalog</Text>
    </View>
  );
}

Fayl yaratdingiz — ekran va uning yo'li tayyor. Hech qanday "ro'yxatga olish" shart emas.


Ekranlar orasida o'tish

Link

import { Link } from 'expo-router';

<Link href="/katalog">Katalogga o'tish</Link>

<Link href="/mahsulot/42" asChild>
  <Pressable style={styles.karta}>
    <Text>iPhone 15</Text>
  </Pressable>
</Link>

asChild — Link o'zi matn chizmaydi, bosishni bolasiga (Pressable) uzatadi. Kartalar va tugmalarni havolaga aylantirish uchun.

router — kodda o'tish

import { router } from 'expo-router';

router.push('/katalog');           // yangi ekranni ustiga qo'yish
router.back();                     // orqaga
router.replace('/bosh');           // joriy ekranni almashtirish (orqaga qaytib bo'lmaydi)
router.navigate('/savat');         // stack da bo'lsa — unga qaytish, bo'lmasa — push
router.dismissAll();               // stack boshiga qaytish
router.canGoBack();                // orqaga yo'l bormi

Qachon kodda? Biror amal tugagandan keyin — masalan, buyurtma yuborilgach:

async function buyurtmaBerish() {
  const id = await api.buyurtma(savat);
  router.replace(`/buyurtma/${id}`);   // replace — orqaga qaytsa formaga emas
}

_layout.tsx — navigatsiya turi

Layout — papkadagi ekranlar qanday ko'rsatilishini belgilaydi:

// app/_layout.tsx
import { Stack } from 'expo-router';

export default function RootLayout() {
  return <Stack />;
}
Layout Nima
<Stack /> Ekranlar ustma-ust, orqaga qaytish (26-dars)
<Tabs /> Pastki tab panel (27-dars)
<Drawer /> Yon menyu (28-dars)
<Slot /> Navigatsiyasiz — faqat joriy ekranni chizadi

Layoutlar ichma-ich bo'ladi — ilovaning butun tuzilmasi papkalar orqali:

app/
├── _layout.tsx               ← Stack (butun ilova)
├── (tabs)/
│   ├── _layout.tsx           ← Tabs
│   ├── index.tsx             ← Bosh tab
│   ├── katalog.tsx           ← Katalog tab
│   └── profil.tsx            ← Profil tab
├── mahsulot/[id].tsx         ← Tablar USTIDA ochiladigan ekran
└── kirish.tsx

Guruhlar: (papka)

Qavsdagi papka — URL ga qo'shilmaydi. (tabs)/katalog.tsx → /katalog, /(tabs)/katalog emas. Guruhlar faqat layoutni ajratish uchun.


Har bir ekran — URL

Expo Router da har bir ekranning manzili bor. Bu uchta imkoniyat beradi:

  1. Deep linking — mening-dokon://mahsulot/42 havolasi (SMS, push, boshqa ilova) to'g'ridan-to'g'ri mahsulot ekranini ochadi (29-dars)
  2. Veb — xuddi shu kod brauzerda haqiqiy URL lar bilan ishlaydi
  3. Tiplangan yo'llar — href="/mahsulotlar/42" da xato bo'lsa, TypeScript ko'rsatadi:
// app.json
"experiments": { "typedRoutes": true }

Maxsus fayllar

Fayl Vazifasi
_layout.tsx Papka layouti
index.tsx Papkaning standart ekrani
[id].tsx Dinamik segment (29-dars)
[...qolgan].tsx Barcha qolgan yo'llar
+not-found.tsx Mavjud bo'lmagan yo'l (404)
(guruh)/ URL siz guruh
// app/+not-found.tsx
import { Link, Stack } from 'expo-router';

export default function TopilmadiEkran() {
  return (
    <>
      <Stack.Screen options={{ title: 'Topilmadi' }} />
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 12 }}>
        <Text style={{ fontSize: 18 }}>Bu sahifa mavjud emas</Text>
        <Link href="/" style={{ color: '#0284c7' }}>Bosh sahifaga</Link>
      </View>
    </>
  );
}

Expo Router va React Navigation

Expo Router ichkarida React Navigation dan foydalanadi — React Native dagi eng ommabop navigatsiya kutubxonasi. Eski loyihalarda React Navigation to'g'ridan-to'g'ri ishlatiladi:

// React Navigation — qo'lda ro'yxatga olish
<Stack.Navigator>
  <Stack.Screen name="Bosh" component={BoshEkran} />
  <Stack.Screen name="Mahsulot" component={MahsulotEkran} />
</Stack.Navigator>

Expo Router da bu ro'yxat — fayllar tuzilmasining o'zi. Tushunchalar (stack, tab, options) bir xil — React Navigation hujjatlarini o'qish ham foydali.


Nima uchun shunday?

Nima uchun mobil ilovaga URL kerak — foydalanuvchi uni ko'rmaydi-ku?

Foydalanuvchi ko'rmaydi, lekin tizim ko'radi. Push bildirishnoma "buyurtmangiz yo'lda" deydi — bosilganda aynan shu buyurtma ekrani ochilishi kerak. Do'stingiz WhatsApp da mahsulot havolasini yubordi — u ilovada ochilishi kerak. Reklama kampaniyasi aniq bir aksiya sahifasiga olib borishi kerak. Har bir ekranning manzili bo'lmasa — bularning hammasi uchun qo'lda murakkab mantiq yoziladi. Fayl asosidagi yo'llar bilan esa har bir ekran avtomatik ravishda "manzilli" bo'ladi.


Xulosa

Eslab qoling:

  • app/ dagi fayl = ekran = URL; export default komponent
  • <Link href="...">, asChild — havola; router.push / back / replace — kodda
  • replace — amal tugagandan keyin (forma ga qaytmaslik uchun)
  • _layout.tsx — Stack, Tabs, Drawer, Slot; ichma-ich bo'ladi
  • (guruh) — URL ga qo'shilmaydigan papka
  • [id].tsx — dinamik, +not-found.tsx — 404
  • typedRoutes — yo'llar TypeScript bilan tekshiriladi
  • Ichkarida — React Navigation

Keyingi dars

26-dars: Stack navigatsiya — sarlavha, orqaga, push/replace