티스토리 뷰
오늘 포스팅에서는 Tanstack Router 설치 및 기본 설정, Router와 NotFound Error처리에 대해 정리해보려고 한다.
아래 명령어를 통해 설치할 수 있으며, 요구사항은 다음과 같다.
- React v18.x.x
- ReactDOM v18.x.x
- Typescript v5.x.x (OPTIONAL)
npm install @tanstack/react-router
만약, Vite나 다른 번들러를 사용한다면 아래 명령어를 이용해 설치한다.
npm install --save-dev @tanstack/router-plugin @tanstack/router-devtools
설치 후에는 vite.config.ts 파일에 아래 내용을 추가한다. (해당 프로젝트에서도 Vite를 사용하고 있다)
// vite.config.ts
import { defineConfig } from 'vite'
import viteReact from '@vitejs/plugin-react'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
TanStackRouterVite(),
viteReact(),
// ...
],
})
또한, 필요에 따라 tsr.config.json 파일을 정의하여 아래의 기본 설정을 변경할 수 있다. 이 외의 다른 옵션 정보는 링크를 통해 자세히 확인할 수 있다. #tsr.config.json Options
{
"routesDirectory": "./src/routes",
"generatedRouteTree": "./src/routeTree.gen.ts",
"routeFileIgnorePrefix": "-",
"quoteStyle": "single"
}
기본적으로 설정된(tsr.config.json에 정의된) routeFileIngorePrefix가 - 이기 때문에 -로 시작하는 파일이나 디렉토리는 라우팅에 고려되지 않는다.
또한, routeFilePrefix와 routeFileIgnorePrefix 옵션을 사용하여 파일 기반 라우팅 설정 시 특정 접두사로 시작하는 파일과 디렉터리만 포함하거나 제외할 수 있다.
Router 클래스는 Tanstack Router의 핵심 기능을 담당하고 있다. 라우트 트리 관리, 라우트 매칭, 네비게이션과 라우트 전환을 조정하는 역할을 한다. 또한, 라우트 전역 설정을 관리하는 역할을 한다.
import { createRouter, RouterProvider } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen.ts';
const router = createRouter({ routeTree });
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
파일 기반 라우팅이든 코드 기반 라우팅이든 createRouter에 라우터 트리를 전달해야한다. 만약 파일 기반 라우팅을 사용했다면 일반적으로 생성된 라우트 트리 파일은 src/routeTree.gen.ts에 생성된다. (사용자 정의 위치를 사용했다면 해당 위치에서 라우트 트리를 가져와야 한다.)
TanStack Router provides amazing support for TypeScript, even for things you wouldn't expect like bare imports straight from the library!
To make this possible, you must register your router's types using TypeScripts'
Declaration Merging feature. This is done by extending the
Register interface on @tanstack/react-router with a router property that has the type of your router instance:
공식 문서를 따라 아래 타입을 정의하고 라우터를 등록하면 애플리케이션 내 라우팅 관련한 모든 것에 대해 타입 안전성을 확보할 수 있다고 한다.
declare module '@tanstack/react-router' {
interface Register {
// This infers the type of our router and registers it across your entire project
router: typeof router
}
}
공식문서에 따르면 아래 방법을 통해 NotFoundRoute를 설정할 수 있다고 기재되어 있다.
import { NotFoundRoute } from '@tanstack/react-router'
import { Route as rootRoute } from './routes/__root.tsx'
const notFoundRoute = new NotFoundRoute({
getParentRoute: () => rootRoute,
component: () => '404 Not Found',
})
const router = createRouter({
routeTree,
notFoundRoute,
})
실제 예제를 따라 작업하며 notFoundRoute가 depredcated됐다는 사실을 알게되었다.
/**
* @deprecated
* Use `notFoundComponent` instead.
* See https://tanstack.com/router/v1/docs/guide/not-found-errors#migrating-from-notfoundroute for more info.
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#notfoundroute-property)
*/
notFoundRoute?: AnyRoute;
Tanstack Router에서 notFound 오류를 두 가지 방법(NotFoundComponent API나 notFound()를 사용)으로 처리할 수 있다. 보통 아래와 같은 상황에 오류가 발생한다. #Not Found Errors
첫 번째, Non-matching route paths (경로가 일치하지 않는 경우)일 때, 자동으로 notFound오류가 발생한다. 보통 이 경우에는 NotFoundComponent API를 이용해 처리할 수 있다.
이 경우에는 NotFoundMode 설정을 통해 오류 처리 방식을 결정할 수 있다. NotFoundMode에는 두 가지 모드가 존재한다.
- fuzzy : 가장 가까운 부모 라우트 중에서 notFoundComponent가 있는 라우트가 오류를 처리한다.
- root : 루트 라우트가 오류를 처리한다.
해당 설정은 Router에서 변경할 수 있다. (공식 문서에 따르면 기본 설정은 "fuzzy"이다.)
const router = createRouter({
routeTree,
notFoundMode: 'fuzzy',
});
아래 코드와 같이 route를 설정했을 때, /learning/1과 같은 접근을 시도하면 fuzzy인 경우, 부모 라우트인 LearningRoute에서 notFoundComponent 설정을 확인하고, LearningRoute의 notFoundComponent를 렌더링한다. 반대로, root인 경우, 같은 접근에 대해 root라우트의 notFoundComponent가 렌더링된다.
import { createFileRoute } from '@tanstack/react-router';
/** learningRoute **/
export const LearningRoute = createFileRoute('/learning')({
component: () => <div>학습 관리 페이지</div>,
notFoundComponent: () => <div> NOT FOUND ERROR </div>,
});
/** root route **/
export const Route = createRootRoute({
component: () => (
<div>
<Link to='/'>Home</Link>
<Link to='/untact'>Untact</Link>
<hr />
<Outlet />
<TanStackRouterDevtools />
</div>
),
notFoundComponent: () => <div>NOT FOUND ERROR - root에서 처리</div>,
});
또 다른 방법으로는 createRouter에서 defaultNotFoundComponent를 설정하여 전역적으로 관리할 수 있다. (Leaf-node 경로들은 아울렛을 렌더링하지 않기 때문에 '경로 없음' 오류를 처리할 수 있는 구조가 아니기 때문에 아래 같은 방법을 적용해 처리할 수 있다)
const router = createRouter({
defaultNotFoundComponent: () => {
return (
<div>
<p>Not found!</p>
<Link to="/">Go home</Link>
</div>
)
},
})
두 번째, Missing resources(누락된 리소스가 있는 경우)일 때, 특정 ID를 가진 포스트가 없거나 존재하지 않는 비동기 데이터를 찾을 때 발생한다. 예를 들어, ID가 1인 포스트가 존재하지 않을 때, /post/1과 같은 접근을 시도한 경우, notFound오류가 발생한다.
이 때에는 notFound()를 사용해 해당 오류를 처리할 수 있다.
notFound()는 redirect와 유사하게 동작한다. 또한, 같은 라우트 또는 가장 가까운 부모 라우트에서 오류를 처리한다. 이를 위해서 defaultNotFoundComponent를 설정하거나 notFoundComponent 설정을 권장하고 있다.
아래 코드는 notFound 사용 예시이다. (각각 routeId를 지정해 사용하거나 rootRouteId를 이용해 처리할 수 있다.)
// 1. notFound()사용하여 처리
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => {
// Returns `null` if the post doesn't exist
const post = await getPost(postId)
if (!post) {
throw notFound()
// Alternatively, you can make the notFound function throw:
// notFound({ throw: true })
}
// Post is guaranteed to be defined here because we threw an error
return { post }
},
})
// 2. layoutId를 지정하여 처리
// _layout/a.tsx
export const Route = createFileRoute('/_layout/a')({
loader: async () => {
// This will make LayoutRoute handle the not-found error
throw notFound({ routeId: '/_layout' })
// ^^^^^^^^^ This will autocomplete from the registered router
},
// This WILL NOT render
notFoundComponent: () => {
return <p>Not found (in _layout/a)</p>
},
})
// 3. rootRouteId 변수를 전달하여 root의 notFoundComponent로 설정하여 처리
import { rootRouteId } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => {
const post = await getPost(postId)
if (!post) throw notFound({ routeId: rootRouteId })
return { post }
},
'REACT' 카테고리의 다른 글
createBrowserRouter 사용하기(React Router v6.4) (0) | 2024.08.11 |
---|---|
Tanstack Router 사용하기 03 (0) | 2024.08.04 |
Tanstack Router 사용하기 01 (6) | 2024.07.24 |
[React] 17. localStorage와 sessionStorage 사용해보기 (1) | 2020.12.28 |
[React] 16. 리덕스로 TodoList구현하기 03 (0) | 2020.12.10 |
- Total
- Today
- Yesterday