[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-09 21:08:02 +09:00
parent f0befc887a
commit 93ec7e9056
363 changed files with 68333 additions and 64 deletions
@@ -0,0 +1,188 @@
---
id: react-tanstack-router-patterns
title: TanStack Router — Type-safe / loader / search params
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [react, router, tanstack-router, vibe-coding]
tech_stack: { language: "TS / React", applicable_to: ["Frontend"] }
applied_in: []
aliases: [TanStack Router, file-based routing, type-safe params, loader, search validation]
---
# TanStack Router
> Type-safe React router. **Search params validation, file-based routing, loader, suspense** 일급. React Router 의 type-safe 버전 + Next 의 file-based.
## 📖 핵심 개념
- File-based: `routes/*.tsx` → 자동 tree.
- Type-safe link: `<Link to="/users/$id" params={{ id: '1' }} />` 컴파일 검증.
- Search params: zod 같은 schema.
- Loader: 라우트 진입 전 데이터 fetch.
## 💻 코드 패턴
### Setup
```bash
yarn add @tanstack/react-router @tanstack/router-plugin
```
```ts
// vite.config.ts
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';
plugins: [TanStackRouterVite()];
```
### Route 정의 (file-based)
```tsx
// src/routes/__root.tsx
import { Outlet, createRootRoute } from '@tanstack/react-router';
export const Route = createRootRoute({ component: () => <Outlet /> });
// src/routes/users.$id.tsx
import { createFileRoute } from '@tanstack/react-router';
import { z } from 'zod';
export const Route = createFileRoute('/users/$id')({
params: { parse: (p) => ({ id: z.string().uuid().parse(p.id) }) },
validateSearch: z.object({ tab: z.enum(['profile', 'orders']).default('profile') }),
loader: async ({ params }) => api.user.get(params.id),
component: UserPage,
});
function UserPage() {
const { id } = Route.useParams(); // typed
const { tab } = Route.useSearch(); // typed
const user = Route.useLoaderData(); // typed
return <h1>{user.name}</h1>;
}
```
### Link (type-safe)
```tsx
import { Link } from '@tanstack/react-router';
<Link to="/users/$id" params={{ id: '42' }} search={{ tab: 'orders' }}>
Profile
</Link>
// 잘못된 path / params 컴파일 에러
```
### Navigate (programmatic)
```tsx
const navigate = Route.useNavigate();
navigate({ to: '/users/$id', params: { id: '42' } });
// 또는 search 만 update
navigate({ search: (prev) => ({ ...prev, tab: 'orders' }) });
```
### Loader + Suspense
```tsx
export const Route = createFileRoute('/posts')({
loader: async () => api.posts.list(),
pendingComponent: () => <Spinner />,
errorComponent: ({ error }) => <Error error={error} />,
component: PostsPage,
});
function PostsPage() {
const posts = Route.useLoaderData();
return ...
}
```
### TanStack Query 통합 (loader 안)
```ts
import { queryOptions } from '@tanstack/react-query';
const userQuery = (id: string) => queryOptions({
queryKey: ['user', id],
queryFn: () => api.user.get(id),
});
export const Route = createFileRoute('/users/$id')({
loader: ({ context, params }) => context.queryClient.ensureQueryData(userQuery(params.id)),
component: UserPage,
});
function UserPage() {
const { id } = Route.useParams();
const { data } = useSuspenseQuery(userQuery(id));
return <h1>{data.name}</h1>;
}
```
### Search params (typed link)
```tsx
<Link to="/posts" search={{ q: 'react', page: 2 }}>Posts</Link>
const { q, page } = Route.useSearch();
```
URL: `/posts?q=react&page=2`.
### Nested layout
```tsx
// routes/_app.tsx — layout
export const Route = createFileRoute('/_app')({
component: () => (
<div className="app">
<Sidebar />
<Outlet />
</div>
),
});
// routes/_app.users.tsx — _app layout 안
export const Route = createFileRoute('/_app/users')({...});
```
### Auth (beforeLoad)
```ts
export const Route = createFileRoute('/admin')({
beforeLoad: async ({ context }) => {
if (!context.auth.user) throw redirect({ to: '/login' });
},
});
```
### Devtools
```tsx
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
<RouterProvider router={router} />
<TanStackRouterDevtools router={router} />
```
## 🤔 의사결정 기준
| 상황 | 추천 |
|---|---|
| Type-safe critical | TanStack Router |
| Next.js | Next App Router (자체) |
| 단순 SPA | React Router 6 |
| 거대 monorepo + 강 types | TanStack Router |
| File-based + SSR | Next / Remix |
| 빠른 prototype | React Router |
## ❌ 안티패턴
- **String path concat**: type 안전 X. params object.
- **Search 검증 없음**: 잘못된 URL 이 crash.
- **Loader 안에 mutation**: 의도와 다름. action 으로.
- **Route 별 `useParams<RouteId>()` 매번 type 인자**: factory 활용.
- **beforeLoad 무거운 작업**: 라우트 진입 느림.
- **404 / pendingComponent 없음**: 빈 화면.
## 🤖 LLM 활용 힌트
- File-based + zod search/params + loader + TQ 통합 4종.
- Vite plugin 자동 generate.
- Devtools 필수 (개발).
## 🔗 관련 문서
- [[React_TanStack_Query_Advanced]]
- [[React_Router_Patterns]]
- [[React_Suspense_for_Data]]