Tanstack Router는 라우트 트리를 만들 때 두가지 방식을 지원한다.
파일 기반 라우팅을 사용하기를 바란다. 더 적은 코드로 같거나 더 나을 결과를 얻어낸다.
만약 /blog/posts/123이라는 URL이 주어졌다고 하자. 그러면 아래와 같은 구조의 Nested된 URL이다.
그러면 컴포넌트 렌더 트리는 다음과 같이 생겼다.
<Blog>
<Posts>
<Post postId="123" />
</Posts>
</Blog>
Tanstack Query는 이런 계층형 라우터를 라우트 트리라고 부른다.
Tanstack Router로 아래 라우터를 모두 표현할 수 있다.
가장 최상단 라우터로 모든 라우터를 포함하는 라우터이다.
path가 없더라도 root Route는 다른 라우터의 기능을 모두 동일하게 수행할 수 있다.
다음은 Root Route 만드는 방법이다.
// src/routes/__roots.tsx
import { createRootRoute } from '@tanstack/react-router';
export const Route = createRootRoute();
Root Route를 제외한 모든 라우터는 FileRoute로 구성된다.
import { createFileRoute } from '@tanstack/react-router';
import { PostsComponent } from '@/src/components/PostComponent';
export const Route = createFileRoute('/posts')({
component: PostsComponent,
});
개발자가 createFileRoute에 path를 넘겨주면 vite plugin이나 Router CLI가 자동으로 라우터 경로를 만들어준다.
/user, /about과 같은 꼴의 정적 페이지를 만들 때 사용한다. 진짜 쉽다.
// src/routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/about')({
component: AboutComponent,
})
function AboutComponent() {
return <div>About</div>
}
Parent Route에는 정확히 맞지만 child Route에는 맞는 것이 없는 경우 사용하는 Route이다. 파일 이름 끝에 index.tsx라고 붙여준다.
아래와 같은 경우 페이지 URL은 /posts이다.
// src/routes/post.index.tsx
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/posts/')({
component: PostsIndexComponent,
});
function PostsIndexComponent() {
return <div>Please select a post!</div>
}
$를 붙여서 반들고 params 객체에서 필요한 slug를 뽑아 먹는 형태이다.
아래와 같은 경우는 /posts/123과 같은 형태의 URL 페이지를 만들 수 있다.
// src/routes/posts/posts.$postId.tsx
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/posts/$postId')({
// In a loader
loader: ({ params }) => fetchPost(params.postId),
// Or in a component
component: PostComponent,
});
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post ID: {postId}</div>
}
신기한건 createFileroute에 넣어준 /posts/$postId에서 params에 postId라는 필드를 $postId로부터 파싱하여 자동으로 생성해준다. 개꿀이다.
$표시를 "splat"이라고 부른다. 만약 /files/documents/hello-world라면 params의 _splat은 documents/hello-world가 된다.
{
'_splat': 'documents/hello-world'
}
파일 라우터는 prefix가 _로 시작하는 경우 Pathless 라우터라고 한다. Pathhless 라우터는 child Route에게 자신의 path를 부여하지 않고 자신의 컴포넌트나 비즈니스 로직을 부여할 수 있다.
만약 _layout이라는 라우터가 있고 이걸로 layout-a와 layout-b를 감싼다면 /layout-a과 layout-b만으로 child routes를 부를 수 있다.
// LayoutA.tsx
<Layout>
<LayoutA />
</Layout>
// LayoutB.tsx
<Layout>
<LayoutB />
</Layout>
// src/_layout.tsx
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/_layout')({
component: LayoutComponent,
});
function LayoutComponent() {
return (
<div>
<h1>Layout</h1>
<Outlet />
</div>
)
}
이해가 잘 가지 않는 나를 위해 영상 하나 넣어둔다.
https://www.youtube.com/watch?v=cTV6zS57Fdg
Non-Nested Routes는 parent 파일 route 이름에 _를 붙이면 된다. 이거 부모 라우터 형태는 유지하면서 Nested가 아닌 라우터 만드는데 유용하다.
path 매칭에서는 _는 무시된다. 그래서 /posts와 /posts_는 같은 path이다. 하지만 컴폰넌트 트리에서는 이 두 가지를 _를 붙여서 구분한다. 따라서 /posts와 /posts_는 다른 라우터로 구분된다.
/posts_/$postId/edit/posts$postId이 경우는 /posts와 /posts_/$postId/edit은 동등한 레벨의 라우터이다. /posts와 /posts/$postId/edit에 부모-자식 관계는 아니다.
// `posts_.$postId.edit.tsx`
<EditPost postId={postId} />
// `posts.$postId.tsx`
<Posts>
<Post postId={postId} />
</Posts>
여기서는 EditPost는 Post의 자식이 아니라서 Post로 쌓여 있지 않다.
없는 페이지 띄우는 라우터이다.
NotFoundRoute가 나타나는 조건은 다음과 같다.
간단히 아래 세 가지 경우로 종합된다.
근데, 얘네들도 똑같이 라우터의 일을 수행할 수 있다.