
✅ clientLoader
export async function clientLoader() {
// await new Promise((resolve) => setTimeout(resolve, 10000));
// const topics = await getTopics();
// const posts = await getPosts();
const [topics, posts] = await Promise.all([getTopics(), getPosts()]);
/* const topics = getTopics();
const posts = getPosts(); */
return { topics, posts };
}
loader fn을 clientLoader로 바꿔주면 server에서 fetching을 하던게 browser에서 fetching을 하게 된다.
export async function loader() {
const [topics, posts] = await Promise.all([getTopics(), getPosts()]);
return { topics, posts };
}
export async function clientLoader({ serverLoader }: Route.ClientLoaderArgs) {
// track analytics
return await serverLoader();
}
그리고 loader와 clientLoader를 같이 사용하면 loader를 clientLoader의 arg에서 serverLoader라는 이름으로 promise 형태로 받기 때문에 await로 실행해줘야 한다.
그리고 그 모든 데이터는 최종적으로 component의 loaderData에 같이 들어가게 된다.
Community 이동
↓
clientLoader 실행
↓
serverLoader() 호출
↓
loader() 실행
↓
{
topics,
posts
}
반환
↓
clientLoader 반환
↓
loaderData에 저장
↓
CommunityPage 렌더
ex)
export async function clientLoader({ serverLoader }: Route.ClientLoaderArgs) {
const data = await serverLoader();
console.log("analytics");
return {
...data,
clientTime: Date.now(),
};
}
loaderData = {
topics,
posts,
clientTime,
};
그래서 정리하면:
- loader만 있으면 → loader의 반환값이 loaderData
- clientLoader만 있으면 → clientLoader의 반환값이 loaderData
- loader + clientLoader 같이 있으면 → clientLoader의 반환값이 최종 loaderData
- 이때 loader 결과를 쓰고 싶으면 serverLoader()를 직접 호출해서 받아와야 함
✅ HydrateFallback
SSR → CSR 전환(hydration) 중 보여줄 임시 UI
export function HydrateFallback() {
return <div>Loading...</div>;
}
Suspense의 fallback과 비슷하지만 차이점은,
Suspense는 특정 컴포넌트를 기다리고
HydrateFallback은 Route 전체를 기다린다.
'📂 라이브러리' 카테고리의 다른 글
| 라이브러리 - React Router v7 - prefetch (1) | 2026.05.29 |
|---|---|
| 라이브러리 - Supabase JavaScript Client Library (0) | 2026.05.27 |
| 라이브러리 - Magic UI (1) | 2026.05.21 |
| 라이브러리 - Simple Icons (0) | 2026.05.15 |
| 라이브러리 - React Router v7 (0) | 2026.05.11 |