発行:
データローディング (Loader)
これまでReactでは、データ取得に useEffect フックを使うのが一般的でした。
しかし、現在のReact Routerでは、ルーティングとデータ取得を統合した Loader という機能が提供されています。
これにより、「ページが表示されてからデータを読み込み始める(Loadingスピナーが出る)」のではなく、「データを読み込んでからページを表示する」といった高度な最適化が可能になります。
Loaderの定義
Loaderは、単なる非同期関数であり、コンポーネントの外(ファイルレベル)で定義するのがベストプラクティスです。
ローダー関数の構成
この関数は、URLパラメータ(:postId など)を含む params オブジェクトを受け取ることができます。
src/PostDetail.jsximport { useLoaderData } from "react-router-dom"; // 1. ローダー関数を定義(コンポーネントの外に置く) export const postDetailLoader = async ({ params }) => { const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.postId}`); if (!response.ok) { // ここでエラーを投げると、後述の errorElement が反応する throw new Error("記事が見つかりませんでした"); } return response.json(); };
useLoaderDataによるデータの受取
コンポーネント内では、useLoaderData フックを使って、ローダーが返したデータを直接受け取ります。
const PostDetail = () => { const post = useLoaderData(); // 型安全にデータを受け取れる return ( <article className="p-8"> <h1 className="text-3xl font-black">{post.title}</h1> <p className="mt-6 leading-relaxed text-slate-400">{post.body}</p> </article> ); };
ルートへの紐付け
定義した loader を、ルーティング設定(createBrowserRouter)に登録します。
ルート定義の更新
パスごとに loader プロパティを指定することで、そのパスに遷移した際に自動的にデータフェッチが走るようになります。
src/main.jsxconst router = createBrowserRouter([ { path: "posts/:postId", element: <PostDetail />, loader: postDetailLoader, // ローダーを登録 errorElement: <ErrorPage />, // エラー発生時のフォールバック }, ]);
errorElementによる宣言的エラーハンドリング
Loader内でエラーが発生した場合、React Routerは element の代わりに errorElement を表示します。これにより、各コンポーネントに if (error) return ... といったボイラープレートを書く必要がなくなります。
Loaderの革新的なメリット
- ウォーターフォール問題の解消 : ネストされたルートがある場合、親と子のデータを 並列 に取得しに行けます。
- 宣言的な状態管理 : 「読み込み中」「エラー」「成功」の状態管理をライブラリ側に任せることができます。
- UXの向上 : データが揃うまで遷移を待機(またはSuspenseで表示)させることができるため、ページのチラつきを抑えられます。