🐇
Remix Loader の発火原因を見極める
はじめに
Remix アプリを開発している際に Loader の発火理由を判定する必要がありました。リンクをクリックした場合と useFetcher を使用した場合で Loader 内の処理を少し変える必要があったためです。
この記事では、試行錯誤の末に見つけた Remix Loader の発火理由を判定する方法を紹介します。
Remix Loader が発火するタイミング
Loaderが発火するタイミングは、主に以下の3つのシチュエーションに分けられます。
-
ページの初回読み込み
- URL を直接入力してアクセスしたときや、ブラウザのリロードが行われたときに、初回のサーバーリクエストが発生し Loader が発火します。
-
内部リンク
-
useFetcher の使用
- Remix の useFetcher フックを使用してデータ取得を行ったとき、指定したセグメントの Loader が発火します。
ページの初回読み込みか判定する方法
export function loader({ request }: LoaderFunctionArgs) {
const dest = request.headers.get('Sec-Fetch-Dest');
if (dest === 'document') {
// ここに入ってきたらページの初回読み込み
}
return { message: 'Hello from the loader!' };
}
HTTP ヘッダーの Sec-Fetch-User を利用することで判定が可能です。値が document であれば、ページの初回読み込みとなります。
remix-utils というライブラリの fetchDest を利用すると、より簡単に Sec-Fetch-User の値が取得できそうです。
内部リンクと useFetcher 使用を判定する方法
export function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const from = url.searchParams.get('from') ?? undefined;
if (dest === 'fetcher') {
// ここに入ってきたら useFetcher を使用しようした読み込み
}
return { message: 'Hello from the loader!' };
}
export default function Index() {
const fetcher = useFetcher();
const handleClick = () => {
if (fetcher.state === 'idle') {
fetcher.load('/xxxxxxxx&from=fetcher');
}
};
return <button onClick={handleClick}>fetch!</button>;
}
URLSearchParams を利用することで判定が可能です。useFetcher 使用する場合は、fetcher.load に指定するエンドポイントを URLSearchParams のフラグ付きにすることで、内部リンクと useFetcher 使用を判定することができます。
本当は、「ページの初回読み込みか判定する方法」と同じように HTTP ヘッダーなどから判定できたら良かったのですが難しそうです。理由は、Remix の Link コンポーネントや navigate で遷移をした場合は、内部的には fetcher.load で遷移先ページの loader が実行され、React Router によって画面が作られるからです。また fetcher.load では、カスタムヘッダーの追加も許されていないです。
Discussion