Files
2nd/10_Wiki/Topics/Coding/React_TanStack_Router_Patterns.md
T
2026-05-09 21:08:02 +09:00

4.9 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
react-tanstack-router-patterns TanStack Router — Type-safe / loader / search params Coding draft B conceptual 2026-05-09 2026-05-09
react
router
tanstack-router
vibe-coding
language applicable_to
TS / React
Frontend
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

yarn add @tanstack/react-router @tanstack/router-plugin
// vite.config.ts
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';
plugins: [TanStackRouterVite()];

Route 정의 (file-based)

// 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>;
}
import { Link } from '@tanstack/react-router';

<Link to="/users/$id" params={{ id: '42' }} search={{ tab: 'orders' }}>
  Profile
</Link>

// 잘못된 path / params 컴파일 에러

Navigate (programmatic)

const navigate = Route.useNavigate();
navigate({ to: '/users/$id', params: { id: '42' } });

// 또는 search 만 update
navigate({ search: (prev) => ({ ...prev, tab: 'orders' }) });

Loader + Suspense

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 안)

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>;
}
<Link to="/posts" search={{ q: 'react', page: 2 }}>Posts</Link>

const { q, page } = Route.useSearch();

URL: /posts?q=react&page=2.

Nested layout

// 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)

export const Route = createFileRoute('/admin')({
  beforeLoad: async ({ context }) => {
    if (!context.auth.user) throw redirect({ to: '/login' });
  },
});

Devtools

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 필수 (개발).

🔗 관련 문서