Dinamik yo'llar va parametrlar — [id].tsx, deep link
Muammodan boshlaylik
Katalogda 2000 ta mahsulot. Har biri uchun alohida ekran fayli yaratish — imkonsiz. Kerak — bitta "mahsulot ekrani" shabloni, qaysi mahsulotni ko'rsatishni esa parametr belgilaydi: /mahsulot/42, /mahsulot/7.
Va yana: do'stingiz WhatsApp da yuborgan mening-dokon://mahsulot/42 havolasini bosganda — ilova ochilib, aynan shu mahsulot ko'rinishi kerak.
Dinamik segment: [id].tsx
app/
└── mahsulot/
└── [id].tsx ← /mahsulot/1, /mahsulot/42, /mahsulot/abc
// app/mahsulot/[id].tsx
import { useLocalSearchParams, Stack } from 'expo-router';
import { View, Text } from 'react-native';
export default function MahsulotEkran() {
const { id } = useLocalSearchParams<{ id: string }>();
return (
<View style={{ flex: 1, padding: 16 }}>
<Stack.Screen options={{ title: `Mahsulot #${id}` }} />
<Text>Mahsulot ID: {id}</Text>
</View>
);
}
- Kvadrat qavsdagi nom — parametr nomi:
[id]→id useLocalSearchParams— parametrlarni oladi- Parametrlar doim string (yoki string massivi). Son kerak bo'lsa —
Number(id)
[!WARNING] URL dan kelgan parametr — foydalanuvchi kiritgan ma'lumot kabi: deep link orqali istalgan qiymat kelishi mumkin (
/mahsulot/abc,/mahsulot/-1). Tekshiring va "topilmadi" holatini ko'rsating.
O'tish
<Link href={`/mahsulot/${mahsulot.id}`}>...</Link>
// Ob'ekt shaklida — tozaroq, maxsus belgilar avtomatik kodlanadi
<Link href={{ pathname: '/mahsulot/[id]', params: { id: mahsulot.id } }}>...</Link>
router.push({ pathname: '/mahsulot/[id]', params: { id: 42 } });
Query parametrlar
Dinamik segmentdan tashqari qo'shimcha parametrlar:
router.push({ pathname: '/katalog', params: { toifa: 'telefonlar', saralash: 'narx' } });
// → /katalog?toifa=telefonlar&saralash=narx
// app/katalog.tsx
const { toifa, saralash = 'yangi' } = useLocalSearchParams<{ toifa?: string; saralash?: string }>();
Joriy ekran parametrini o'zgartirish (filtr o'zgarganda, yangi ekran ochmasdan):
router.setParams({ saralash: 'narx' });
URL — holatning bir qismi: filtr URL da bo'lsa, uni havola orqali ulashish va deep link bilan ochish mumkin.
Nimani parametrda uzatmaslik kerak
// ❌ Butun ob'ekt
router.push({ pathname: '/mahsulot/[id]', params: { id: 42, mahsulot: JSON.stringify(mahsulot) } });
// ✅ Faqat ID — ma'lumotni ekranning o'zi yuklaydi (yoki keshdan oladi)
router.push({ pathname: '/mahsulot/[id]', params: { id: 42 } });
Sabablari: URL uzunligi cheklangan; deep link bilan kelganda ob'ekt bo'lmaydi; ma'lumot eskirgan bo'lishi mumkin. TanStack Query (32-dars) ro'yxatdagi ma'lumotni keshda saqlaydi — mahsulot ekrani darhol ochiladi.
Boshqa dinamik naqshlar
app/
├── toifa/[toifa]/[id].tsx ← /toifa/telefonlar/42 → { toifa, id }
├── [...yol].tsx ← /a/b/c → { yol: ['a', 'b', 'c'] }
└── foydalanuvchi/[[...tab]].tsx ← /foydalanuvchi va /foydalanuvchi/postlar (ixtiyoriy)
useLocalSearchParams va useGlobalSearchParams farqi: Local — faqat shu ekran fokusda bo'lganda yangilanadi; Global — har qanday URL o'zgarishida. Deyarli doim — Local (ortiqcha qayta chizishdan saqlaydi).
Deep linking
Har bir ekranning URL i bor (25-dars) — demak tashqaridan ochish mumkin.
1. Sxema
// app.json
{ "expo": { "scheme": "mening-dokon" } }
Endi mening-dokon://mahsulot/42 — ilovani ochib, mahsulot ekraniga o'tadi.
2. Sinash
# Android emulyator yoki ulangan telefon
npx uri-scheme open "mening-dokon://mahsulot/42" --android
# iOS simulator
npx uri-scheme open "mening-dokon://mahsulot/42" --ios
Expo Go da sxema boshqacha (exp://...), shuning uchun to'liq sinov — development build da (48-dars).
3. Kodda havola yasash
import * as Linking from 'expo-linking';
const havola = Linking.createURL(`/mahsulot/${id}`);
// development: exp://192.168.1.10:8081/--/mahsulot/42
// production: mening-dokon://mahsulot/42
Universal links / App Links
mening-dokon:// havolasi faqat ilova o'rnatilgan bo'lsa ishlaydi. Yaxshiroq — oddiy https havola:
https://dokon.uz/mahsulot/42
- Ilova o'rnatilgan → ilovada ochiladi
- O'rnatilmagan → saytda ochiladi
Buning uchun saytingizda maxsus fayllar (apple-app-site-association, assetlinks.json) va app.json da associatedDomains (iOS) / intentFilters (Android) sozlanadi. Bu ishlab chiqarish bosqichidagi vazifa — Expo hujjatlarida bosqichma-bosqich.
Push bildirishnomadan ochish
Bildirishnoma ma'lumotida yo'l yuboriladi:
{ "title": "Buyurtmangiz yo'lda", "data": { "url": "/buyurtma/1043" } }
Bosilganda — router.push(data.url). 42-darsda to'liq.
Nima uchun shunday?
Nima uchun parametrlar doim string — id ni son sifatida uzatsam, son bo'lib kelmaydimi?
Chunki parametrlar URL orqali o'tadi, URL esa matn. Deep link, bildirishnoma yoki brauzerdan kelganda hech qanday "tur" haqida ma'lumot yo'q — faqat /mahsulot/42 qatori. Agar ilova ichida o'tganda son, tashqaridan kelganda string bo'lsa — ikki xil xatti-harakat va qiyin topiladigan xatolar. Doim string — doim bir xil: ekran parametrni qanday kelganidan qat'i nazar bir xil yo'l bilan tekshiradi va aylantiradi.
Xulosa
Eslab qoling:
[id].tsx— dinamik segment;useLocalSearchParams<{ id: string }>()- Parametrlar doim string —
Number(id), tekshirish va "topilmadi" holati href={{ pathname: '/mahsulot/[id]', params: { id } }}— ob'ekt shaklida- Query parametrlar — filtr va saralash;
router.setParams - Faqat ID uzating, butun ob'ektni emas
[...yol]— qolgan barcha segmentlar- Deep link:
scheme+Linking.createURL; production — universal / app links
Keyingi dars
30-dars: Autentifikatsiya oqimi — himoyalangan ekranlar