すみません、釣りです Gemini に某ちびっこ探偵団の名台詞を使ってタイトルを生成してみたんですが、いまいちですね。
はじめに
JISOU というコミュニティに参加しており、react-router を使って課題に取り組んでいたのですが気づきがあったので備忘録です。
何が起きたのか
ルーティングは app/routes.ts
を使って定義しました。
import { type RouteConfig, route } from "@react-router/dev/routes";
export default [
route("home", "routes/home.tsx"),
route("individuals", "routes/individuals.tsx"),
route("blogs", "routes/blogs.tsx"),
] satisfies RouteConfig;
routes/individuals.tsx
には次のような loader を定義しました。
export async function loader() {
return { qiitaItems: qiita.fetchItems() }
}
同じように routes/blogs.tsx
には次のような loader を定義しました。
export async function loader() {
return { microcmsItems: microcms.fetchContents() }
}
イケてる定義かはさておき、routes/blogs.tsx
のなかで loader を呼び出そうとすると、エラーになりました。
export default function blogs({ loaderData }: Route.ComponentProps) {
let { microcmsItems } = loaderData
...
}
// formatted by Gemini
Property 'microcmsItems' does not exist on type '{
qiitaItems: Promise<
{
id: string;
title: string;
url: string;
thumbnail: string;
created_at: string;
}[]
>;
}'.
どこがわるかったのか
react-router の型定義は .react-router/types/app/routes/+types
に出力します。これを 適切なパスを指定する 必要があります。つまり routes/blogs.tsx
では
import type { Route } from "./+types/blogs";
と参照する必要があります。これを別コンポーネントを指定すると、わたしが直面したエラーになります。
どうしておきたのか
routes/individuals.tsx
を作ったあとで 同じ画面構成だしコピペちゃえ と routes/blogs.tsx
を作りました。運転免許を取得したての人がよく事故るケースに近いですね。「あ、おれ運転(react-router)得意かも」で事故る。
事故防止?の方法もあるには、ある
useLoaderData
を使いましょう。ドキュメントによると次のようにあり、ファイルにある loader
を使って型を参照してくれます。
最も近いルートのloaderからシリアライズされたデータを返します。
引用:https://remix-docs-ja.techtalk.jp/hooks/use-loader-data
export default function blogs() {
let { microcmsItems } = useLoaderData<typeof loader>();
...
}
おわりに
コピペ絶対だめ