Mundarija (27)
- Bu darsda
- 1. Nega bu kerak?
- 2. "Jim" xatolar: React Router'da qanday ko'rinadi
- 2.1 useParams() — har kalit mumkin
- 2.2 Yo'llar ro'yxati — tur bo'lsa
- 3. TanStack Router: marshrut daraxti kod bilan
- 3.1 O'rnatish va narxi
- 3.2 Uch sahifa — router-tanstack.tsx
- 3.3 Parametr — bir marta parse
- 3.4 Register — router'ni TypeScript'ga tanishtirish
- 4. O'lchov: tsc nimani ushladi
- 5. So'rov parametrlari: validateSearch
- 5.1 Muammo: ?sahifa=abc
- 5.2 Xuddi shu g'oya — React Router'da, Zod bilan
- 6. Fayl asosidagi marshrutlar, devtools va TanStack Start
- 7. Kanon tajribasi: nega vazifalar React Router'da qoldi
- 7.1 Hajm
- 7.2 Qaror
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): qaysi xato?
- 2-mashq (o'rta): literal tur bilan yo'l
- 3-mashq (qiyin): URL sxemasi
- 4-mashq: vazifalar ga nazar
- 10. Real ishda
- Xulosa
- Manbalar
TanStack Router: to'liq type-safe routing, validateSearch va React Router bilan o'lchab taqqoslash
Qisqacha: TanStack Router — React uchun router, unda yo'llar, parametrlar va so'rov parametrlari (search params) TypeScript turlari bilan tekshiriladi. Masalan,
<Link to="/vazifalar/$id">— yo'q yo'l bo'lsa,tscxato beradi.params.id— son, chunki marshrut uni bir martaparseqiladi.validateSearch(masalan, Zod sxemasi bilan)?sahifa=abcni ham tozalaydi.vazifalarda o'lchandi: 93.2 KB (React Router — 97.3), ataylab yozilgan 4 xatonitscushladi, React Router — birortasini ham. Kanon React Router'da qoldi: kurs ekotizimi va Next.js'ga ko'prik.
Bu darsda
- "Type-safe routing" nimani anglatishini va React Router qayerda "jim" qolishini ko'rasiz.
- TanStack Router'da marshrut daraxtini kod bilan qurasiz:
createRootRoute,createRoute,createRoutervaRegister. - Parametrlarni
parse/stringifybilan son qilasiz, so'rov parametrlarinivalidateSearchva Zod bilan tekshirasiz. - Fayl asosidagi marshrutlar (
@tanstack/router-plugin), devtools va TanStack Start nima ekanini bilasiz. - Kanon o'lchovini o'qib, qaysi loyihaga qaysi router mosligini tanlay olasiz.
Oldin bilishingiz kerak: React Router IV: data mode, Union va literal turlar, Zod va turni sxemadan chiqarish.
1. Nega bu kerak?
Sardor vazifalar ga yangi havola qo'shdi: <Link to={`/vazifalar/${id}`}>. Ko'zi tushmadi — marshrut /vazifa/:id, oxirida ortiqcha "lar". tsc indamadi, ESLint indamadi, testlar o'tdi. Foydalanuvchi bosdi — 404.
Boshqa safar useParams() dan params.idd deb o'qidi (imlo xatosi). Natija — undefined, Number(undefined) — NaN, vazifa "topilmadi". Yana hech kim ogohlantirmadi.
Sabab bitta: React Router uchun yo'l — oddiy satr. U qanday marshrutlar borligini TypeScript'ga aytmaydi. 06-darsda framework mode'ning typegen'i buni qisman hal qilishini ko'rdik — lekin u alohida build qadami va Vite plagini bilan. TanStack Router boshqacha yo'l tutadi: marshrut daraxtining o'zi TypeScript turi, hech qanday generatsiyasiz.
Hayotiy o'xshatish: taksi navigatori. Biri manzilni qo'lda yozdirib, xato bo'lsa haydab ketib, joyida "bunday ko'cha yo'q" deydi. Ikkinchisi manzilni faqat xaritadagi ro'yxatdan tanlatadi — noto'g'ri ko'chani tanlab bo'lmaydi.
2. "Jim" xatolar: React Router'da qanday ko'rinadi
2.1 useParams() — har kalit mumkin
React Router'da useParams() ning turi — { [key: string]: string | undefined }. Ya'ni har qanday kalit "bor bo'lishi mumkin". Quyidagi blok — TypeScript (tsx): sayt uni tsc bilan tekshiradi va ishga tushiradi. Imlo xatosiga qaramay, tur tekshiruvi xatosiz o'tadi:
import {
createMemoryRouter,
RouterProvider,
useParams,
} from "react-router";
function Task() {
const params = useParams();
const id = Number(params.idd); // imlo xatosi: idd
return <p>Vazifa raqami: {String(id)}</p>;
}
const router = createMemoryRouter(
[{ path: "/vazifa/:id", element: <Task /> }],
{ initialEntries: ["/vazifa/2"] },
);
export default function App() {
return <RouterProvider router={router} />;
}Ekranda:
Vazifa raqami: NaNSahifa — NaN, tsc ham, brauzer ham indamadi. Kanon tajribasida (tajriba/tip-xatolar/router-xato.tsx) xuddi shu qator bor va izohi: "idd — imlo xatosi, tsc indamaydi".
2.2 Yo'llar ro'yxati — tur bo'lsa
Bu muammoni qanday hal qilish mumkin? Barcha yo'llarni literal turlar birlashmasi qilib yozamiz. Shunda Link faqat ro'yxatdagi yo'lni qabul qiladi:
type RoutePath = "/" | "/vazifa/$id" | "/statistika";
function linkTo(to: RoutePath): string {
return to;
}
linkTo("/vazifa/$id");
linkTo("/vazifalar/$id");Xato:
TS2345: Argument of type '"/vazifalar/$id"' is not assignable to parameter of type 'RoutePath'.Ikkinchi chaqiruv qizil: "/vazifalar/$id" turi RoutePath ga mos emas. TanStack Router shu g'oyani oxirigacha olib boradi. Yo'llar ro'yxatini siz yozmaysiz — u marshrut daraxtidan o'zi chiqariladi. Har yo'lning parametrlari ($id), ularning turi (son) va so'rov parametrlari ham turga kiradi.
3. TanStack Router: marshrut daraxti kod bilan
3.1 O'rnatish va narxi
npm i --save-exact @tanstack/react-router@1.170.41Kanon tajribasidagi versiya — 1.170.41 (2026-09-30; o'lchov kunida eng yangisi 1.170.44 edi, 7 kundan yangi bo'lgani uchun olinmadi — natijalar/versiyalar.txt). Natija oynasida bu paket yo'q — saytdagi «Ishga tushir» faqat React Router'ni yuklaydi. Shuning uchun bu bo'limdagi TanStack kodlari tekshirilmagan bloklar; ularning hammasi kanon tajriba faylidan aynan olingan va tsc dan o'tgan.
3.2 Uch sahifa — router-tanstack.tsx
vazifalar ning o'sha uch sahifasi (kanon tajribasi, aynan; uzun qatorlar telefon uchun bo'lingan):
import {
createRootRoute,
createRoute,
createRouter,
Link,
notFound,
Outlet,
RouterProvider,
} from "@tanstack/react-router";
const ildizMarshrut = createRootRoute({
component: () => (
<>
<nav>
<Link to="/">Ro'yxat</Link>
</nav>
<Outlet />
</>
),
notFoundComponent: () => <p>Topilmadi</p>,
});
const royxatMarshrut = createRoute({
getParentRoute: () => ildizMarshrut,
path: "/",
component: () => (
<ul>
{VAZIFALAR.map((v) => (
<li key={v.id}>
<Link to="/vazifa/$id" params={{ id: v.id }}>
{v.matn}
</Link>
</li>
))}
</ul>
),
});Tanish narsalar boshqa nom bilan:
| TanStack Router | React Router | Izoh |
|---|---|---|
createRootRoute({ component }) |
ildiz { path: "/", element } |
layout, <Outlet /> — o'sha |
createRoute({ getParentRoute, path }) |
children ichidagi obyekt |
ota — funksiya bilan |
$id |
:id |
dinamik segment |
notFoundComponent |
{ path: "*" } |
404 |
<Link to params> |
<Link to={`/vazifa/${id}`}> |
parametr — alohida obyekt |
Eng muhim farq — oxirgi qatorda. Yo'l — shablon ("/vazifa/$id"), parametr — alohida. Shuning uchun tsc ikkalasini ham tekshira oladi: shablon ro'yxatdami, params da aynan id bormi.
Tekshirib ko'ring: React Router'da
<Link to={/vazifa/${v.id}}>yozardik. TanStack'da negaparams={{ id: v.id }}alohida beriladi — bitta satr qulayroq emasmi?
Javob
Bitta satr — TypeScript uchun "qandaydir satr": u ichidagi /vazifa/ ni ham, ${v.id} ni ham ajrata olmaydi. Shablon ("/vazifa/$id") va parametrlar obyekti alohida bo'lsa, tsc ikkita aniq savolga javob beradi: shablon ro'yxatdami va params aynan shu shablon kutgan kalitlarga egami. Narxi — biroz uzunroq yozuv.
getParentRoute: () => ildizMarshrut — nega funksiya? TypeScript turni ota marshrutdan oladi. Funksiya aylana importlarda (fayllar bir-birini import qilsa) ham ishlaydi.
3.3 Parametr — bir marta parse
export const vazifaMarshrut = createRoute({
getParentRoute: () => ildizMarshrut,
path: "/vazifa/$id",
// URL'dagi satr → son (bir marta, shu yerda); stringify —
// teskarisi
params: {
parse: (p) => ({ id: Number(p.id) }),
stringify: (p) => ({ id: String(p.id) }),
},
loader: ({ params }) => {
const v = VAZIFALAR.find((x) => x.id === params.id);
if (!v) throw notFound();
return v;
},
component: function Vazifa() {
const v = vazifaMarshrut.useLoaderData();
return <h2>{v.matn}</h2>;
},
});params.parse— URL'dan kelgan satrni bir marta, marshrut darajasida songa aylantiradi. Loader'daparams.id—number,Number(...)ni har joyda takrorlash yo'q. 03-darsdagi "parametr doim satr" qoidasini marshrutning o'zi hal qiladi.stringify— teskari yo'l:<Link params={{ id: 2 }}>dagi sonni manzilga yozish uchun.loader— React Router'dagidek: sahifadan oldin.throw notFound()—data(…, { status: 404 })o'rni.vazifaMarshrut.useLoaderData()— hook marshrut obyektining o'zidan. Turni loader'dan oladi:v.matn—string,typeofyozish shart emas.
3.4 Register — router'ni TypeScript'ga tanishtirish
export const router = createRouter({
routeTree: ildizMarshrut.addChildren([
royxatMarshrut,
vazifaMarshrut,
]),
});
declare module "@tanstack/react-router" {
interface Register {
router: typeof router;
}
}addChildren — daraxtni yig'adi. Keyingi qism — module augmentation: kutubxonaning Register interfeysiga bizning router turimiz qo'shiladi. Shundan keyin ilovaning istalgan joyidagi <Link> hamma yo'llarni biladi. Bu qadam unutilsa, Link ham oddiy satr qabul qiladigan bo'lib qoladi — type-safety jimgina o'chadi.
4. O'lchov: tsc nimani ushladi
Kanon ataylab xato fayl yozdi (tajriba/tip-xatolar/router-xato.tsx, aynan):
export function Xatolar() {
const rr = useParams(); // xato bo'lsa ham jim
const id: number = Number(rr.idd); // "idd" — tsc indamaydi
return (
<>
{/* 1) mavjud bo'lmagan yo'l */}
<TLink to="/vazifalar/$id" params={{ id: 1 }} />
{/* 2) parametr nomi xato */}
<TLink to="/vazifa/$id" params={{ idd: 1 }} />
{/* 3) parametr turi xato (parse — son kutadi) */}
<TLink to="/vazifa/$id" params={{ id: "bir" }} />
{/* React Router: shu xatolar — tsc jim (satr shablon) */}
<RLink to={`/vazifalar/${id}`} />
</>
);
}TLink — TanStack'ning Link, RLink — React Router'niki. tsc 7.0.2 natijasi (natijalar/tajriba/08-tanstack-tip.txt, uzun tur matnlari qisqartirilgan):
router-xato.tsx(14,14): error TS2820: Type '"/vazifalar/$id"' is not assignable to type '"." | ".." | "/" | "/vazifa/$id"'. Did you mean '"/vazifa/$id"'?
router-xato.tsx(14,44): error TS2353: Object literal may only specify known properties, and 'id' does not exist in type 'ParamsReducerFn<…>'.
router-xato.tsx(16,41): error TS2353: Object literal may only specify known properties, and 'idd' does not exist in type 'ParamsReducerFn<…>'.
router-xato.tsx(18,41): error TS2322: Type 'string' is not assignable to type 'number'.To'rtta xato, uchta qatorda. Ularni o'qiymiz:
- TS2820 — "
/vazifalar/$id" yo'llar ro'yxatiga mos emas. Ro'yxat ham ko'rsatilgan:"." | ".." | "/" | "/vazifa/$id". Va maslahat: "/vazifa/$idni nazarda tutdingizmi?" - TS2353 (14-qator) — yo'l noma'lum bo'lgani uchun
paramsdagiidham "ortiqcha". Bitta xato — ikkita xabar, bu tabiiy. - TS2353 (16-qator) —
idd— bunday parametr yo'q. - TS2322 —
id: "bir"— satr,parseesa son qaytaradi,paramsson kutadi.
React Router qatorlari (rr.idd va RLink) — birorta ham xato yo'q. Uzun ParamsReducerFn<RouterCore<…>> matni — TanStack turlarining narxi: xato xabarlari ba'zan juda uzun. Asosiy qismi — boshida va oxirida.
- React Router 8.4.0 (data mode)0 ta
- TanStack Router 1.170.414 ta
Manba: O'lchandi: tajriba/tip-xatolar/router-xato.tsx, tsc 7.0.2, natijalar/tajriba/08-tanstack-tip.txt, 2026-10-13
5. So'rov parametrlari: validateSearch
5.1 Muammo: ?sahifa=abc
04-darsda useSearchParams() bilan ishladik: qiymat — satr yoki null, tekshirish — har komponentda qo'lda. ?sahifa=abc, ?saralash=pitsa — URL'ni har kim yozadi.
TanStack Router so'rov parametrlarini ham marshrutga bog'laydi. validateSearch — URL'dagi xom obyektni oladi va tekshirilgan, turli obyekt qaytaradi:
const menyuMarshrut = createRoute({
getParentRoute: () => ildizMarshrut,
path: "/menyu",
validateSearch: (search: Record<string, unknown>) => ({
sahifa: Number(search.sahifa ?? 1) || 1,
turi: search.turi === "ichimlik" ? "ichimlik" : "hammasi",
}),
});
// komponentda: const { sahifa, turi } = menyuMarshrut.useSearch();
// sahifa — number, turi — "ichimlik" | "hammasi"
// <Link to="/menyu" search={{ sahifa: 2 }}> — turi tekshiriladiFunksiya o'rniga Zod sxemasini ham berish mumkin: TanStack Router Standard Schema'ni (Zod 4, Valibot ham shu standartda) to'g'ridan qabul qiladi. Bu blok o'lchanmagan — kanon tajribasida validateSearch yo'q edi.
5.2 Xuddi shu g'oya — React Router'da, Zod bilan
TanStack'siz ham bu naqshni qo'llash mumkin. Sxema bir marta yoziladi, komponent tekshirilgan qiymat oladi. Natija oynasida zod/mini bor (kanondagi Zod — API qatlami darsida batafsil):
import {
createMemoryRouter,
RouterProvider,
useLocation,
useSearchParams,
} from "react-router";
import * as z from "zod/mini";
// URL — foydalanuvchi kiritgan ma'lumot: tekshir, yaroqsizini
// almashtir
const menuSearch = z.object({
sahifa: z.catch(z.coerce.number().check(z.int(), z.positive()), 1),
turi: z.catch(z.enum(["hammasi", "ichimlik"]), "hammasi"),
});
function useMenuSearch() {
const [params, setParams] = useSearchParams();
const search = menuSearch.parse(Object.fromEntries(params));
return [search, setParams];
}
function Menu() {
const { search: raw } = useLocation();
const [search, setParams] = useMenuSearch();
return (
<section>
<p>URL: {raw}</p>
<p>
Sahifa {search.sahifa}, turi: {search.turi}
</p>
<button
onClick={() =>
setParams({ sahifa: String(search.sahifa + 1) })
}
>
Keyingi
</button>
</section>
);
}
const router = createMemoryRouter(
[{ path: "/menyu", element: <Menu /> }],
{ initialEntries: ["/menyu?sahifa=abc&turi=pitsa"] },
);
export default function App() {
return <RouterProvider router={router} />;
}Ekranda:
URL: ?sahifa=2
Sahifa 2, turi: hammasi
KeyingiIlova ?sahifa=abc&turi=pitsa bilan ochildi — ikkalasi ham yaroqsiz. z.catch(…, 1) — "tekshiruvdan o'tmasa, shu qiymat": sahifa 1, turi "hammasi". «Keyingi» — sahifa=2. z.coerce.number() — satrni songa aylantiradi (Zod chuqurroq darsida). Komponent hech qachon NaN yoki "pitsa" ni ko'rmaydi.
Farq: bu yerda search.sahifa turi JavaScript'da tekshirilmaydi, TypeScript'da esa faqat useMenuSearch ichida ma'lum. <Link to="/menyu?sahifa=abc"> ni yozishga hech narsa to'sqinlik qilmaydi. TanStack'da search={{ sahifa: "abc" }} — tsc xatosi.
Tekshirib ko'ring: Yuqoridagi ilova
/menyu?sahifa=-3bilan ochilsa, ekranda qaysi sahifa?/menyu?sahifa=2.5chi?
Javob
Ikkalasida ham 1. -3 — son, lekin z.positive() dan o'tmaydi. 2.5 — z.int() dan o'tmaydi. Har qanday tekshiruv xatosida z.catch zaxira qiymatni beradi. Sxemasiz Number("-3") — -3 bo'lardi va ro'yxat "−3-sahifa" ni qidirardi.
6. Fayl asosidagi marshrutlar, devtools va TanStack Start
Fayl asosidagi marshrutlar (file-based routing). Katta ilovada createRoute ni qo'lda yozish o'rniga @tanstack/router-plugin (Vite plagini) ishlatiladi. Fayllar src/routes/ da: __root.tsx, index.tsx, vazifa.$id.tsx. Plagin ulardan routeTree.gen.ts faylini generatsiya qiladi — yuqoridagi addChildren daraxtining o'zi. Har marshrut fayli createFileRoute("/vazifa/$id")({ … }) bilan boshlanadi. Hujjat shu yo'lni tavsiya qiladi. Kanon tajribasi kod bilan ("generator'siz") yozilgan — daraxt ko'rinib tursin.
Devtools. @tanstack/react-router-devtools — dev rejimida sahifa burchagidagi panel: joriy marshrutlar, parametrlar, loader holati, kesh. React Router'da bunday rasmiy panel yo'q.
TanStack Start — shu router ustiga qurilgan full-stack framework: SSR, server funksiyalar. React Router'ning framework mode'iga (06-dars) yoki Next.js'ga muqobil. Bu kursda o'tilmaydi — nomini eshitsangiz, nima ekanini bilasiz.
Kesh va TanStack Query. TanStack Router loader natijasini o'zi keshlaydi (staleTime bilan) va TanStack Query bilan oson birlashadi. Query'ni TanStack Query I darsidan o'rganamiz.
7. Kanon tajribasi: nega vazifalar React Router'da qoldi
7.1 Hajm
- faqat React66,5 KB
- TanStack Router 1.170.4193,2 KB
- React Router 8.4.097,3 KB
Manba: O'lchandi: tajriba/qur.mjs, Vite 8.3.3, gzip -9, natijalar/tajriba/hajm.txt (router-tanstack 93 247 B, router-rr 97 262 B, _umumiy 66 470 B), 2026-10-13
TanStack Router 4 KB kichik (93 247 va 97 262 bayt). Ikkalasi ham bir xil ishni qiladi: layout, ro'yxat, loader'li vazifa sahifasi, 404. Ikkalasi ham faqat build qilindi va tsc dan o'tdi — brauzerda bosib solishtirilmadi.
7.2 Qaror
QADAMLAR (19/#08): kirmadi. Sabablar:
- Yo'nalish — kurs ekotizimi React Router: data mode g'oyalari (loader, action,
<Form>) to'g'ridan Next.js qismiga ko'prik. React Router — npm'da eng ko'p yuklanadigan React router'i; ish e'lonlarida ham u ko'proq. - Ko'chish narxi — 02–07 darslarda qurilgan hamma narsa (marshrutlar,
Himoyalangan, loader, 45 ta e2e tekshiruv) qayta yoziladi.
Lekin raqamlar halol: TanStack kichikroq va type-safe — kanon buni TEXNIK-QARZ.md ga (46-band) yozib qo'ygan. Shunday vaziyatda TanStack Router to'g'ri tanlov bo'ladi:
- yangi, katta TypeScript ilova — o'nlab sahifa, ko'p filtr va so'rov parametri (admin panel, CRM);
- jamoa TanStack Query'ni allaqachon ishlatadi;
- URL holati ko'p (
?sahifa=&saralash=&filtr=) —validateSearchuni bir joyga yig'adi.
React Router ham shu yo'nalishda yuryapti: framework mode'dagi typegen (06-dars) href() va Route.ComponentProps orqali yo'l va parametrlarni tekshiradi. Farqi — TanStack'da turlar marshrut kodining o'zidan chiqadi, React Router'da esa alohida generatsiya qadami va Vite plagini kerak. Data mode'da (bizning vazifalar) bu tekshiruv yo'q. Shuning uchun vazifalar da yo'llar testlar bilan himoyalangan: 19-qismning e2e tekshiruvlari asosiy havolalarni brauzerda bosib ko'radi.
Kichik ilova yoki SSR kerak bo'lgan ochiq sayt uchun — React Router (framework mode) yoki Next.js.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
Link har qanday satrni qabul qiladi |
Register e'lon qilinmagan |
declare module … interface Register { router: typeof router } |
TS2820: … Did you mean … |
yo'l ro'yxatda yo'q | maslahat qilingan yo'lni yozing |
params.id — satr, === 2 hech qachon true emas |
params.parse yo'q |
parse: (p) => ({ id: Number(p.id) }) |
uzun ParamsReducerFn<RouterCore<…>> xabar |
murakkab generic turlar | xabarning boshi va oxirini o'qing: qaysi kalit, qaysi tur |
routeTree.gen.ts topilmadi |
plagin ishlamagan | @tanstack/router-plugin Vite'da, dev serverni qayta ishga tushiring |
React Router'da ?sahifa=abc → NaN |
qiymat tekshirilmagan | sxema (z.catch) bilan bir joyda o'qish |
9. Mashqlar
Mashqlar kurs/mashqlar/19/08-tanstack-router/ da.
1-mashq (oson): qaysi xato?
TanStack Router'da / va /taom/$slug marshrutlari bor (slug — satr). Har qatorga tsc nima deydi: "toza" yoki xato kodi (TS2820, TS2353, TS2322)?
<Link to="/taom/$slug" params={{ slug: "osh" }} />→<Link to="/taomlar/$slug" params={{ slug: "osh" }} />→<Link to="/taom/$slug" params={{ nom: "osh" }} />→
Yechim
1 — toza. 2 — TS2820: yo'l ro'yxatda yo'q (va TS2353 ham chiqishi mumkin — «O'lchov» bo'limidagi 14-qatordagidek, yo'l noma'lum bo'lsa parametr ham "ortiqcha"). 3 — TS2353: nom degan parametr yo'q, slug kerak. React Router'da uchala qator ham tsc dan jim o'tardi.
2-mashq (o'rta): literal tur bilan yo'l
RoutePath turini yozing ("/", "/menyu", "/taom/$slug") va linkTo funksiyasi faqat shularni qabul qilsin. $slug ni slug qiymati bilan almashtirsin. Ishora: «Yo'llar ro'yxati — tur bo'lsa» bo'limi va satrning replace metodi.
Yechim
type RoutePath = "/" | "/menyu" | "/taom/$slug";
function linkTo(to: RoutePath, slug = ""): string {
return to.replace("$slug", slug);
}
console.log(linkTo("/menyu"));
console.log(linkTo("/taom/$slug", "osh"));
export default function App() {
return <a href={linkTo("/taom/$slug", "manti")}>Manti</a>;
}Konsolda:
/menyu
/taom/oshEkranda:
MantilinkTo("/taomlar/$slug") endi tsc xatosi beradi. Kamchilik: "/menyu" ga ham slug berish mumkin, "/taom/$slug" ga esa bermaslik ham mumkin. TanStack Router buni ham hal qiladi: parametrlar yo'lga qarab majburiy yoki taqiqlangan bo'ladi — bunga bitta conditional type kerak.
3-mashq (qiyin): URL sxemasi
«Bahor» buyurtmalar sahifasi /buyurtmalar?holat=…&saralash=…. Sxema yozing:
holat—"yangi" | "tayyor" | "hammasi", noto'g'ri bo'lsa"hammasi".saralash—"vaqt" | "narx", sukut"vaqt".- Ekranda:
Holat: …, saralash: …. «Tayyorlar» tugmasiholat=tayyorni qo'ysin,saralashni saqlagan holda.
Ilova /buyurtmalar?holat=bekor&saralash=narx bilan ochilsin. Ishora: «Xuddi shu g'oya — React Router'da» bo'limi va 04-darsdagi funksiya bilan setSearchParams.
Yechim
import {
createMemoryRouter,
RouterProvider,
useSearchParams,
} from "react-router";
import * as z from "zod/mini";
const ordersSearch = z.object({
holat: z.catch(z.enum(["yangi", "tayyor", "hammasi"]), "hammasi"),
saralash: z.catch(z.enum(["vaqt", "narx"]), "vaqt"),
});
function Orders() {
const [params, setParams] = useSearchParams();
const search = ordersSearch.parse(Object.fromEntries(params));
return (
<section>
<p>
Holat: {search.holat}, saralash: {search.saralash}
</p>
<button
onClick={() =>
setParams((prev) => {
prev.set("holat", "tayyor");
return prev;
})
}
>
Tayyorlar
</button>
</section>
);
}
const router = createMemoryRouter(
[{ path: "/buyurtmalar", element: <Orders /> }],
{ initialEntries: ["/buyurtmalar?holat=bekor&saralash=narx"] },
);
export default function App() {
return <RouterProvider router={router} />;
}Ekranda:
Holat: tayyor, saralash: narx
TayyorlarOchilganda holat=bekor yaroqsiz — "hammasi", saralash=narx — to'g'ri, saqlandi. «Tayyorlar» funksiya bilan yozdi — saralash yo'qolmadi. saralash URL'da bo'lmasa ham "vaqt" bo'lardi: z.catch yo'q qiymatni ham ushlaydi (undefined enum'dan o'tmaydi).
4-mashq: vazifalar ga nazar
Darsdagi TanStack kodini («Parametr — bir marta parse») data mode darsidagi vazifaLoader bilan solishtiring. Har birida vazifa raqami URL'dan songa qayerda aylanadi?
Yechim
React Router variantida — loader ichida (raqaminiOl → Number(id)); har yangi joyda qaytadan yoziladi. TanStack variantida — marshrut ta'rifida bir marta: params.parse. Loader ham, Link ham songa ishlaydi (params={{ id: v.id }} — son), satrga aylantirishni stringify qiladi. Shu sababli 3-xato (id: "bir") TanStack'da tsc xatosi.
10. Real ishda
- Katta TypeScript ilovalar — TanStack Router 2023-yildan beri tez o'smoqda, ayniqsa admin panel va SaaS loyihalarda, TanStack Query bilan birga.
- Migratsiya — React Router'dan TanStack'ga ko'chish odatda bosqichma-bosqich emas, bir martada (ikki router birga ishlamaydi). Shuning uchun tanlov loyiha boshida qilinadi.
- URL holati —
validateSearchnaqshi kutubxonasiz ham foydali: sxema + bitta hook. Keyingi darsdanuqskutubxonasini ko'ramiz. - Intervyu savollari: "type-safe routing nima beradi?", "
paramsqachon satr, qachon son?", "URL'dagi qiymatni qanday tekshirasiz?".
Xulosa
- React Router'da yo'l va
useParams()— oddiy satr: imlo xatositscdan jim o'tadi. - TanStack Router:
createRootRoute,createRoute({ getParentRoute, path }),createRouter+Register— yo'llar turga aylanadi. params.parse— parametr bir marta, marshrutda songa;validateSearch— so'rov parametrlari sxema bilan.- O'lchov: 93.2 vs 97.3 KB, ataylab yozilgan 4 xato — TanStack ushladi, React Router — 0.
- Fayl asosidagi marshrutlar —
@tanstack/router-plugin; devtools; TanStack Start — full-stack. - Kanon React Router'da qoldi (ekotizim, Next.js ko'prigi, ko'chish narxi); yangi katta TS ilova uchun TanStack — kuchli nomzod.
Keyingi dars: URL — holat saqlash joyi — filtr, saralash va sahifa URL'da: nuqs, standart qiymatlarni tozalash, push va replace. vazifalar ning filtri router'ga ko'chadi.
Manbalar
- TanStack Router: Overview, Code-based Routing, Type Safety, Search Params — tanstack.com/router/latest/docs (2026-10 holatiga, v1.170)
- TanStack Router: File-based Routing, Router Plugin, Devtools — tanstack.com/router/latest/docs/framework/react
- React Router:
useParams— reactrouter.com/api/hooks/useParams - Zod 4:
zod/mini,catch,coerce— zod.dev
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!