【Remix v2 -> React Router v7】useLoaderDataで取得したいデータの型情報を指定したい
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ4Oh74YCl8GGZWu9blT6gf3iWaMGTrHvZi377Q3rEU9NTmQ7rAju6pMrRf6xogxGTWuV7Z7-YczGQTD3VF8QvyN_QQA4CFWwFrzg8bOIRJPv_su1IdNdrUDQVRxtcAIlV2VXahy4wB7M/s800/space_ijuu_moon.png
【前提】
code:routes/members/$id.tsx
export async clientLoader ({ params }: ClientLoaderFunctionArgs) {
if (params.id === 'tascript') {
return redirect('/home')
}
const member: Member = await getMembers('1')
return {
member
}
}
...
export deafault function Index() {
const data = useLoaderData<typeof clientLoader>()
...
}
このページでは特定のパスパラメータ(tascript)が含まれた状態でアクセスすると/homeにリダイレクトします。それ以外はパスパラメータを利用して特定のメンバー情報をclientLoaderからコンポーネントに送信します。コンポーネント内ではuseLoaderdataを利用し、メンバー情報を取得しています。
しかし、React Routerにマイグレーション後、memberプロパティへのアクセスをするとTypeScriptではエラーになります。というのも、clinetLoaderではリダイレクトする可能性があるので、返り値がPrmomise<Response | { member: Member }>で表現されます。useLoaderDataではGenericsとしてclientLoaderの型情報を参照しているので、Promise<Response>の可能性がある型情報のままではmemberプロパティにアクセスできません。
このような場合はどうすればよいでしょうか。
【結論】
関数をオーバーロードしましょう。こうすることで関数の呼び出し方法を複数持つことができます。今回は、clientLoaderの返り値がPrmomise<{ member: Member }>で表現されるようにオーバーロードします。 code:routes/members/$id.tsx
export async clientLoader ({ params }: ClientLoaderFunctionArgs): Prmomise<{ member: Member }>
export async clientLoader ({ params }: ClientLoaderFunctionArgs) {
if (params.id === 'tascript') {
return redirect('/home')
}
const member: Member = await getMembers('1')
return {
member
}
}
...
export deafault function Index() {
const data = useLoaderData<typeof clientLoader>()
...
}
関数をオーバーロードし、返り値の型情報を追加したことで、memberプロパティへのアクセスを型安全に実行することができました。
【余談】