Data Loading
데이터 로딩은 웹 애플리케이션에서 흔히 발생하는 문제로 라우팅과 관련이 있습니다. 애플리케이션의 페이지를 로드할 때, 해당 페이지의 비동기 요구 사항을 가능한 한 빨리 병렬로 가져와 충족시키는 것이 이상적입니다. 라우터는 콘텐츠가 렌더링되기 전에 사용자가 어디로 이동하고 있는지 알 수 있는 애플리케이션의 유일한 위치이므로 이러한 비동기 종속성을 조정하기에 가장 적합한 위치입니다.
Next.js의 getServerSideProps
나 Remix/React-Router의 loader
와 유사한 기능이 TanStack Router에도 존재합니다. 이 기능은 라우트별로 자산을 사전 로드/로드하여 React가 가능한 한 빨리 서스펜스를 통해 렌더링할 수 있도록 합니다.
이와 같은 일반적인 라우터 기능 외에도, TanStack Router는 내장된 SWR Caching을 제공합니다. 이는 라우트 로더를 위한 장기 메모리 캐싱 계층으로, 라우트 데이터를 즉시 로드하거나 이전에 방문한 라우트 데이터를 임시로 캐싱하여 나중에 다시 사용할 수 있도록 해줍니다.
The route loading lifecycle
URL/히스토리 업데이트가 감지될 때마다 라우터는 다음과 같은 순서로 실행됩니다:
- Route Matching (Top-Down)
route.params.parse
route.validateSearch
- Route Pre-Loading (Serial)
route.beforeLoad
route.onError
route.errorComponent
/parentRoute.errorComponent
/router.defaultErrorComponent
- Route Loading (Parallel)
route.component.preload?
route.loader
route.pendingComponent
(Optional)route.component
route.onError
route.errorComponent
/parentRoute.errorComponent
/router.defaultErrorComponent
To Router Cache or not to Router Cache?
TanStack Router의 캐시는 대부분의 소규모 및 중간 규모 애플리케이션에 적합할 가능성이 높지만, TanStack Query와 같은 더 강력한 캐싱 솔루션을 사용하는 것과의 트레이드오프를 이해하는 것이 중요합니다.
TanStack Router Cache Pros
- 내장되어 있으며 사용하기 쉽고 추가 종속성이 필요하지 않음
- 라우트별로 디듀핑, 사전 로딩, 로딩, SWR, 백그라운드 리패칭을 처리
- 대규모 무효화(모든 라우트 및 캐시를 한 번에 무효화)
- 자동 가비지 컬렉션
- 라우트 간 공유 데이터가 적은 앱에 적합
- SSR에서 "그냥 동작함"
TanStack Router Cache Cons
- 영구 저장소 어댑터/모델 없음
- 라우트 간 공유 캐싱/디듀핑 없음
- 내장된 뮤테이션 API 없음 (
useMutation
훅이 예제에서 제공되며 많은 사용 사례에서 충분히 활용 가능) - 내장된 캐시 수준 낙관적 업데이트 API 없음 (컴포넌트 수준에서
useMutation
훅과 같은 휘발성 상태를 사용해 이를 구현 가능)
[!TIP] TanStack Query와 같은 더 강력한 캐싱 솔루션을 사용하려는 경우 External Data Loading 가이드를 참조하세요.
Using the Router Cache
라우터 캐시는 내장되어 있으며, 라우트의 loader
함수에서 데이터를 반환하기만 하면 됩니다. 예제를 통해 배워봅시다!
Route loader
s
라우트의 loader
함수는 라우트 매칭이 로드될 때 호출됩니다. 이 함수는 여러 유용한 속성을 포함하는 객체를 매개변수로 받습니다. 다음은 간단한 예제입니다:
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
});
loader
Parameters
loader
함수는 다음 속성을 가진 객체를 매개변수로 받습니다:
abortController
- 라우트의 AbortController. 라우트가 언로드되거나 호출이 더 이상 유효하지 않을 때 신호가 취소됩니다.cause
- 현재 라우트 매칭의 원인으로,enter
또는stay
중 하나입니다.context
- 라우트의 컨텍스트 객체로, 상위 라우트의 컨텍스트와beforeLoad
옵션에서 제공된 컨텍스트를 병합한 값입니다.deps
-Route.loaderDeps
함수에서 반환된 객체 값입니다. 정의되지 않은 경우 빈 객체가 제공됩니다.location
- 현재 위치params
- 라우트의 경로 매개변수parentMatchPromise
-Promise<RouteMatch>
(루트 라우트의 경우 undefined
)preload
- 라우트가 로드 대신 사전 로드 중인지 나타내는 Boolean 값route
- 라우트 객체 자체
Consuming data from loader
s
loader
의 데이터를 소비하려면 Route 객체에 정의된 useLoaderData
훅을 사용하세요.
const posts = Route.useLoaderData();
컴포넌트 트리 깊숙한 곳에서 라우트 객체에 접근할 수 없다면 getRouteApi
를 사용하여 동일한 훅 및 Route 객체의 다른 훅에 접근할 수 있습니다. 이는 라우트 객체를 직접 가져오는 것보다 선호되며 순환 종속성을 생성할 가능성을 줄입니다.
import { getRouteApi } from "@tanstack/react-router";
// 컴포넌트 내부에서
const routeApi = getRouteApi("/posts");
const data = routeApi.useLoaderData();
Dependency-based Stale-While-Revalidate Caching
TanStack Router는 라우트 로더를 위한 내장 Stale-While-Revalidate 캐싱 계층을 제공합니다. 이 캐싱은 라우트의 종속성에 기반합니다:
- 라우트의 완전히 파싱된 경로 이름
- 예:
/posts/1
vs/posts/2
- 예:
loaderDeps
옵션으로 제공되는 추가 종속성- 예:
loaderDeps: ({ search: { pageIndex, pageSize } }) => ({ pageIndex, pageSize })
- 예:
이 종속성을 키로 사용하여 TanStack Router는 라우트의 loader
함수에서 반환된 데이터를 캐싱하고 동일한 라우트 매칭에 대한 후속 요청을 처리합니다. 즉, 라우트 데이터가 이미 캐시에 있다면 즉시 반환되며, 데이터의 "신선도"에 따라 백그라운드에서 새로고침될 수도 있습니다.
Key options
라우트 종속성과 "신선도"를 제어하기 위해 TanStack Router는 다양한 옵션을 제공합니다. 다음은 사용 빈도가 높은 순서대로 정리된 옵션들입니다:
routeOptions.loaderDeps
- 라우터의 검색 매개변수를 제공하고 이를
loader
함수에서 사용할 종속성 객체로 반환하는 함수입니다. 이러한 종속성이 탐색 간에 변경되면staleTime
값과 관계없이 라우트가 다시 로드됩니다. 종속성은 깊은 동등성 비교를 통해 비교됩니다.
- 라우터의 검색 매개변수를 제공하고 이를
routeOptions.staleTime
routerOptions.defaultStaleTime
- 라우트 데이터를 로드할 때 데이터가 신선하다고 간주되는 밀리초 수입니다.
routeOptions.preloadStaleTime
routerOptions.defaultPreloadStaleTime
- 사전 로드 시 라우트 데이터가 신선하다고 간주되는 밀리초 수입니다.
routeOptions.gcTime
routerOptions.defaultGcTime
- 라우트 데이터가 캐시에 유지되는 시간(밀리초)입니다.
routeOptions.shouldReload
beforeLoad
및loaderContext
매개변수와 동일한 매개변수를 받고 라우트를 다시 로드할지 여부를 나타내는 부울 값을 반환하는 함수입니다. 이 옵션은staleTime
및loaderDeps
외에도 라우트를 다시 로드해야 하는 시점을 제어할 수 있는 추가적인 제어 수준을 제공합니다. Remix의shouldLoad
옵션과 유사한 패턴을 구현하는 데 사용할 수 있습니다.
⚠️ Some Important Defaults
- 기본적으로
staleTime
은0
으로 설정되어 있습니다. 즉, 라우트 데이터는 항상 신선하지 않은 것으로 간주되며 라우트가 다시 매칭될 때마다 백그라운드에서 다시 로드됩니다. - 기본적으로, 사전 로드된 라우트는 30초 동안 신선하다고 간주됩니다. 즉, 사전 로드된 라우트가 30초 내에 다시 사전 로드되면 두 번째 사전 로드는 무시됩니다. 이는 불필요한 사전 로드가 너무 자주 발생하지 않도록 방지합니다. 라우트가 정상적으로 로드될 때는 기본
staleTime
값이 사용됩니다. - 기본적으로
gcTime
은 30분으로 설정되어 있습니다. 이는 30분 동안 접근되지 않은 라우트 데이터가 캐시에서 가비지 수집되고 제거된다는 의미입니다. router.invalidate()
는 모든 활성 라우트가 즉시 로더를 다시 로드하도록 강제하며, 모든 캐시된 라우트 데이터를 신선하지 않은 것으로 표시합니다.
Using loaderDeps
to access search params
/posts
라우트가 검색 매개변수 offset
및 limit
을 통해 일부 페이지 매김을 지원한다고 가정해 봅시다. 캐시에서 이 데이터를 고유하게 저장하려면 loaderDeps
함수를 통해 이러한 검색 매개변수에 접근해야 합니다. 이를 명시적으로 식별하면, /posts
에 대해 다른 offset
및 limit
값을 가진 각 라우트 매칭이 혼합되지 않습니다.
이 종속성을 설정하면 종속성이 변경될 때마다 라우트가 항상 다시 로드됩니다.
// /routes/posts.tsx
export const Route = createFileRoute("/posts")({
loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
loader: ({ deps: { offset, limit } }) =>
fetchPosts({
offset,
limit,
}),
});
Using staleTime
to control how long data is considered fresh
기본적으로 탐색 시 staleTime
은 0
ms(사전 로드의 경우 30초)로 설정되어 있습니다. 이는 라우트 데이터가 항상 신선하지 않은 것으로 간주되며, 라우트가 매칭되고 탐색될 때마다 백그라운드에서 다시 로드됨을 의미합니다.
대부분의 사용 사례에서 이 기본값은 적합하지만, 일부 라우트 데이터가 더 정적이거나 로드 비용이 비싸다면 staleTime
옵션을 사용하여 탐색 시 데이터가 신선하다고 간주되는 기간을 제어할 수 있습니다. 다음은 예제입니다:
// /routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
// 10초 동안 라우트 데이터를 신선하다고 간주합니다.
staleTime: 10_000,
});
staleTime
옵션에 10_000
을 전달하면, 라우터는 라우트 데이터를 10초 동안 신선하다고 간주합니다. 이는 사용자가 /about
에서 /posts
로 탐색할 때, 마지막 로더 결과로부터 10초 이내라면 라우트 데이터가 다시 로드되지 않음을 의미합니다. 사용자가 10초 후에 /about
에서 /posts
로 탐색하면 라우트 데이터가 백그라운드에서 다시 로드됩니다.
Turning off stale-while-revalidate caching
라우트에 대해 Stale-While-Revalidate 캐싱을 비활성화하려면 staleTime
옵션을 Infinity
로 설정하십시오:
// /routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
staleTime: Infinity,
});
모든 라우트에 대해 이를 비활성화하려면 라우터의 defaultStaleTime
옵션을 설정하십시오:
const router = createRouter({
routeTree,
defaultStaleTime: Infinity,
});
Using shouldReload
and gcTime
to opt-out of caching
Remix의 기본 기능과 유사하게, 라우트를 처음 진입 시 또는 주요 로더 종속성이 변경될 때만 로드하도록 구성하고 싶을 수 있습니다. 이는 gcTime
옵션과 shouldReload
옵션을 조합하여 구현할 수 있습니다. shouldReload
옵션은 boolean
값을 받거나 beforeLoad
및 loaderContext
와 동일한 매개변수를 받고 라우트를 다시 로드할지 여부를 나타내는 부울 값을 반환하는 함수를 받을 수 있습니다.
// /routes/posts.tsx
export const Route = createFileRoute("/posts")({
loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
loader: ({ deps }) => fetchPosts(deps),
// 라우트 데이터가 언로드된 후 캐시하지 않습니다.
gcTime: 0,
// 사용자가 라우트로 이동하거나 종속성이 변경될 때만 라우트를 다시 로드합니다.
shouldReload: false,
});
Opting out of caching while still preloading
라우트 데이터에 대해 단기 캐싱을 비활성화하더라도, 사전 로드의 이점을 여전히 누릴 수 있습니다! 위의 구성에서는 기본 preloadGcTime
을 사용하여 사전 로드가 계속 "그냥 동작"합니다. 즉, 라우트를 사전 로드한 후 탐색하면 라우트 데이터가 신선하다고 간주되며 다시 로드되지 않습니다.
사전 로드를 비활성화하려면 routerOptions.defaultPreload
또는 routeOptions.preload
옵션을 사용하지 마세요.
Passing all loader events to an external cache
이 사용 사례는 External Data Loading 페이지에서 더 자세히 설명되지만, TanStack Query와 같은 외부 캐시를 사용하고자 하는 경우 모든 로더 이벤트를 외부 캐시에 전달할 수 있습니다. 기본값을 사용하는 한, 변경해야 할 유일한 사항은 라우터의 defaultPreloadStaleTime
옵션을 0
으로 설정하는 것입니다:
const router = createRouter({
routeTree,
defaultPreloadStaleTime: 0,
});
이렇게 하면 모든 사전 로드, 로드, 리로드 이벤트가 loader
함수를 트리거하며, 이 함수는 외부 캐시에서 처리되고 디듀핑될 수 있습니다.
Using Router Context
loader
함수에 전달되는 context
매개변수는 다음을 병합한 객체입니다:
- 상위 라우트 컨텍스트
beforeLoad
옵션에서 제공된 현재 라우트의 컨텍스트
라우터의 최상단에서 context
옵션을 통해 초기 컨텍스트를 라우터에 전달할 수 있습니다. 이 컨텍스트는 라우터의 모든 라우트에서 사용할 수 있으며, 라우트가 매칭될 때마다 각 라우트에 복사되고 확장됩니다. 이는 beforeLoad
옵션을 통해 라우트에 컨텍스트를 전달함으로써 이루어집니다. 이 컨텍스트는 라우트의 모든 자식 라우트에서 사용할 수 있습니다. 결과 컨텍스트는 라우트의 loader
함수에서 사용 가능합니다.
다음 예제에서는 라우트 컨텍스트에서 게시글을 가져오는 함수를 생성한 다음 이를 loader
함수에서 사용하는 방법을 보여줍니다.
🧠 컨텍스트는 의존성 주입을 위한 강력한 도구입니다. 이를 사용하여 서비스, 훅, 기타 객체를 라우터 및 라우트에 주입할 수 있습니다. 또한 라우트의
beforeLoad
옵션을 사용하여 라우트 트리를 따라 데이터를 점진적으로 전달할 수도 있습니다.
/utils/fetchPosts.tsx
export const fetchPosts = async () => {
const res = await fetch(`/api/posts?page=${pageIndex}`);
if (!res.ok) throw new Error("Failed to fetch posts");
return res.json();
};
/routes/__root.tsx
import { createRootRouteWithContext } from "@tanstack/react-router";
// createRootRouteWithContext<{...}>() 함수를 사용하여 루트 라우트를 생성하고, 라우터 컨텍스트에서 사용할 수 있는 타입을 전달합니다.
export const Route = createRootRouteWithContext<{
fetchPosts: typeof fetchPosts;
}>()(); // 주의: 이중 호출은 의도된 것이며, createRootRouteWithContext는 팩토리 함수입니다.
/routes/posts.tsx
import { createFileRoute } from "@tanstack/react-router";
// postsRoute가 컨텍스트를 참조하여 fetchPosts 함수를 가져오는 것을 확인하세요.
// 이는 라우터와 라우트 전반에서 의존성 주입을 위한 강력한 도구가 될 수 있습니다.
export const Route = createFileRoute("/posts")({
loader: ({ context: { fetchPosts } }) => fetchPosts(),
});
/router.tsx
import { routeTree } from "./routeTree.gen";
// routerContext를 사용하여 새 라우터를 생성합니다.
// 이는 routerContext의 타입 요구 사항을 충족해야 합니다.
const router = createRouter({
routeTree,
context: {
// fetchPosts 함수를 라우터 컨텍스트에 제공
fetchPosts,
},
});
Using Path Params
loader
함수에서 경로 매개변수를 사용하려면 함수 매개변수의 params
속성을 통해 접근하세요. 다음은 예제입니다:
// routes/posts.$postId.tsx
export const Route = createFileRoute("/posts/$postId")({
loader: ({ params: { postId } }) => fetchPostById(postId),
});
Using Route Context
전역 컨텍스트를 라우터에 전달하는 것은 유용하지만, 특정 라우트에 컨텍스트를 제공해야 한다면 어떻게 할까요? 여기서 beforeLoad
옵션이 사용됩니다. beforeLoad
옵션은 라우트를 로드하기 직전에 실행되는 함수로, loader
와 동일한 매개변수를 받습니다. 이 함수는 잠재적인 매칭을 리디렉션하거나, 로더 요청을 차단하는 등의 기능 외에도, 라우트의 컨텍스트에 병합될 객체를 반환할 수 있습니다. 다음은 beforeLoad
옵션을 통해 라우트 컨텍스트에 데이터를 주입하는 예제입니다:
// /routes/posts.tsx
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/posts")({
// fetchPosts 함수를 라우트 컨텍스트에 전달
beforeLoad: () => ({
fetchPosts: () => console.info("foo"),
}),
loader: ({ context: { fetchPosts } }) => {
console.info(fetchPosts()); // 'foo'
// ...
},
});
Using Search Params in Loaders
❓ 그런데 Tanner... 내 검색 매개변수는 어디 있나요?!
검색 매개변수가 loader
함수의 매개변수에서 직접 사용할 수 없는 이유가 궁금할 수 있습니다. 이를 의도적으로 설계한 이유를 살펴보겠습니다:
loader
함수에서 검색 매개변수를 사용하는 것은 해당 검색 매개변수가 로드된 데이터를 고유하게 식별하는 데 사용되어야 함을 나타내는 좋은 지표입니다. 예를 들어,pageIndex
와 같은 검색 매개변수를 사용하는 라우트가 있다고 가정해 보세요. 이 경우,pageIndex
는 라우트 매칭 내 데이터를 고유하게 식별합니다./users/user
라우트가userId
검색 매개변수를 사용하여 특정 사용자를 식별하는 애플리케이션을 상상해 보세요. URL은/users/user?userId=123
와 같이 모델링될 수 있습니다. 이 경우user
라우트는 특정 사용자를 식별하는 데 추가적인 도움이 필요합니다.- 검색 매개변수를
loader
함수에서 직접 접근하면, 로드된 데이터가 현재 URL 경로 이름 및 검색 매개변수와 고유하지 않을 때 캐싱 및 사전 로드와 관련된 버그로 이어질 수 있습니다. 예를 들어,/posts
라우트에서 2페이지의 결과를 사전 로드하도록 요청했지만, 라우트 구성에서 페이지 간의 구분이 없으면/posts
또는?page=1
화면에서 2페이지 데이터를 가져오고 저장하고 표시하게 됩니다. - 검색 매개변수와
loader
함수 간에 기준을 두면 라우터가 종속성과 반응성을 이해할 수 있습니다.
// /routes/users.user.tsx
export const Route = createFileRoute("/users/user")({
validateSearch: (search) =>
search as {
userId: string;
},
loaderDeps: ({ search: { userId } }) => ({
userId,
}),
loader: async ({ deps: { userId } }) => getUser(userId),
});
Accessing Search Params via routeOptions.loaderDeps
// /routes/posts.tsx
export const Route = createFileRoute("/posts")({
// zod를 사용하여 검색 매개변수를 검증하고 파싱
validateSearch: z.object({
offset: z.number().int().nonnegative().catch(0),
}),
// loaderDeps 함수를 통해 검색 매개변수 offset을 전달
loaderDeps: ({ search: { offset } }) => ({ offset }),
// loader 함수에서 컨텍스트에서 offset 사용
loader: async ({ deps: { offset } }) =>
fetchPosts({
offset,
}),
});
Using the Abort Signal
loader
함수의 abortController
속성은 AbortController (opens in a new tab)입니다. 라우트가 언로드되거나 loader
호출이 더 이상 유효하지 않을 때 신호가 취소됩니다. 이는 라우트가 언로드되거나 라우트의 매개변수가 변경될 때 네트워크 요청을 취소하는 데 유용합니다. 아래는 fetch 호출과 함께 사용하는 예제입니다:
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: ({ abortController }) =>
fetchPosts({
// 하위 fetch 호출 또는 신호를 지원하는 다른 작업에 전달
signal: abortController.signal,
}),
});
Using the preload
flag
loader
함수의 preload
속성은 라우트가 로드 대신 사전 로드 중일 때 true
인 부울 값입니다. 일부 데이터 로딩 라이브러리는 표준 fetch와 다르게 사전 로드를 처리할 수 있으므로 preload
를 데이터 로딩 라이브러리에 전달하거나 적절한 데이터 로딩 로직을 실행하는 데 사용할 수 있습니다:
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: async ({ preload }) =>
fetchPosts({
maxAge: preload ? 10_000 : 0, // 사전 로드는 조금 더 오래 유지되어야 합니다.
}),
});
Handling Slow Loaders
대부분의 라우트 로더는 짧은 시간 내에 데이터를 해결하여 플레이스홀더 스피너를 렌더링할 필요 없이 서스펜스를 통해 다음 라우트를 완전히 준비되었을 때 렌더링할 수 있어야 합니다. 그러나 라우트 컴포넌트를 렌더링하는 데 필요한 중요한 데이터가 느린 경우 다음 두 가지 옵션이 있습니다:
- 빠른 데이터와 느린 데이터를 별도의 promise로 나누고 느린 데이터를 빠른 데이터가 로드된 후까지
defer
(지연)합니다. (Deferred Data Loading 가이드 참조) - 모든 데이터가 준비될 때까지 낙관적 서스펜스 임계값 이후에 대기 중인 컴포넌트를 표시합니다. (아래 참조)
Showing a pending component
기본적으로 TanStack Router는 해결 시간이 1초를 초과하는 로더에 대해 대기 중인 컴포넌트를 표시합니다. 이 낙관적 임계값은 다음을 통해 구성할 수 있습니다:
routeOptions.pendingMs
또는routerOptions.defaultPendingMs
대기 시간이 초과되면, 라우터는 라우트의 pendingComponent
옵션을 렌더링합니다(구성된 경우).
Avoiding Pending Component Flash
대기 중인 컴포넌트를 사용하는 경우, 대기 시간 임계값이 충족된 후 데이터가 바로 해결되어 대기 중인 컴포넌트가 깜빡이는 상황을 원치 않을 것입니다. 이를 방지하기 위해 TanStack Router는 기본적으로 대기 중인 컴포넌트를 최소 500ms 동안 표시합니다. 이 낙관적 임계값은 다음을 통해 구성할 수 있습니다:
routeOptions.pendingMinMs
또는routerOptions.defaultPendingMinMs
Handling Errors
TanStack Router는 라우트 로딩 라이프사이클 중 발생하는 오류를 처리하는 몇 가지 방법을 제공합니다. 살펴보겠습니다.
Handling Errors with routeOptions.onError
routeOptions.onError
옵션은 라우트 로딩 중 오류가 발생했을 때 호출되는 함수입니다.
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
onError: ({ error }) => {
// 오류 로그 기록
console.error(error);
},
});
Handling Errors with routeOptions.onCatch
routeOptions.onCatch
옵션은 라우터의 CatchBoundary에서 오류가 잡혔을 때 호출되는 함수입니다.
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
onCatch: ({ error, errorInfo }) => {
// 오류 로그 기록
console.error(error);
},
});
Handling Errors with routeOptions.errorComponent
routeOptions.errorComponent
옵션은 라우트 로딩 또는 렌더링 라이프사이클 중 오류가 발생했을 때 렌더링되는 컴포넌트입니다. 이 컴포넌트는 다음과 같은 props를 사용하여 렌더링됩니다:
error
- 발생한 오류reset
- 내부CatchBoundary
를 재설정하는 함수
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
errorComponent: ({ error }) => {
// 오류 메시지 렌더링
return <div>{error.message}</div>;
},
});
reset
함수는 사용자가 에러 경계의 일반적인 자식을 다시 렌더링하도록 재시도할 수 있게 합니다:
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
errorComponent: ({ error, reset }) => {
const router = useRouter();
return (
<div>
{error.message}
<button
onClick={() => {
// 라우터 에러 경계를 재설정
reset();
}}
>
retry
</button>
</div>
);
},
});
오류가 라우트 로드로 인해 발생한 경우, router.invalidate()
를 호출하여 라우터 리로드와 에러 경계 재설정을 모두 조정해야 합니다:
// routes/posts.tsx
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
errorComponent: ({ error, reset }) => {
const router = useRouter();
return (
<div>
{error.message}
<button
onClick={() => {
// 라우트를 무효화하여 로더를 다시 로드하고 에러 경계를 재설정
router.invalidate();
}}
>
retry
</button>
</div>
);
},
});
Using the default ErrorComponent
TanStack Router는 라우트 로딩 또는 렌더링 라이프사이클 중 오류가 발생했을 때 렌더링되는 기본 ErrorComponent
를 제공합니다. 라우트의 오류 컴포넌트를 재정의하는 경우에도 기본 ErrorComponent
를 사용하여 모든 처리되지 않은 오류를 렌더링하는 것이 좋습니다:
// routes/posts.tsx
import { createFileRoute, ErrorComponent } from "@tanstack/react-router";
export const Route = createFileRoute("/posts")({
loader: () => fetchPosts(),
errorComponent: ({ error }) => {
if (error instanceof MyCustomError) {
// 사용자 정의 오류 메시지 렌더링
return <div>{error.message}</div>;
}
// 기본 ErrorComponent로 폴백
return <ErrorComponent error={error} />;
},
});