
はじめに
React Router を使ったコンポーネントでよく出るエラーのひとつが、useParams() で URL パラメータが取得できずにテストが落ちることでした。
ここでは、そのエラーの原因と解決方法を整理します。
useParams()とは
React Router のフックのひとつです。
const { id } = useParams();
このように書くと、/user/abc123 のようなURLから id: "abc123" を取得できる。
ただしRouterコンテキストの中でしか使えないです。
今回は useParams を使って、URLの id に応じたユーザーの個人ページ(例:/taro → 太郎さんのページ)を表示するために使いました。
エラーの例
TypeError: Cannot read properties of undefined (reading 'id')
このエラーは useParams() で id を読み込もうとしているのに、
テスト中は id を持つ URL パラメータが渡っていない状態で起こりました。
エラーの原因n
const { id } = useParams();
上記のようなコードがあるコンポーネント(例:Card)を
テストでこう書いて失敗しました。
render(Card />); // ← URL が無い
useParams() は React Router のコンテキストが無いと動きません。
MemoryRouter で仮URLを与えて解決
テストでは MemoryRouter を使って、仮の URL を与えます。
MemoryRouterとは
React Router の Router の一種で、
テスト中に「仮のURL履歴」を作るためのラッパーです
initialEntries
MemoryRouter に渡す initialEntries は、仮のURL履歴を表す配列です。
このように書くと、最初にアクセスしているURLを「/taro」と仮定してくれます。
これにより、useParams() が正しく id: “taro” を返すようになります。
render(
MemoryRouter initialEntries={["/taro"]}>
Routes>
Route path="/:id" element={Card />} />
Routes>
MemoryRouter>
);
これで useParams() が { id: "taro" } を返せるようになります。
つまずいたポイント
-
useParams()はRouterコンテキストの中でしか使えない - 単体で
をrender()するだけではパラメータが入らない -
MemoryRouter+initialEntriesを知らないとテストが通らなかった
まとめ
-
useParams()が必要なコンポーネントはMemoryRouterで包む -
initialEntriesで仮のURLを渡す -
Route path="/:id"とelement={}を組み合わせる
Views: 2
