現在個人プロジェクトでReactを使って開発しています。
その中で react-router v6 を使用しているのですが、v5とは仕様が変わっていて上手く動かなかったので少し内容を記事に書き起こそうと思います。
まずコンソールに表示されていたメッセージはこちらです。
You rendered descendant <Routes> (or called `useRoutes()`) at "/report" (under <Route path="/report">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
親ルート配下の子ルートをレンダリングしようとしたときに *
ワイルドカード指定が無いからパスがマッチせずレンダリングできませんでしたという内容のものです。
手元のコードは以下になります。(記事向けにコード内容をところどころ崩しています)
main.tsx
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <React.StrictMode> <BrowserRouter> <Routes> <Route path="/" element={<App />} errorElement={<ErrorPage />} />; <Route path="/hoge" element={<HogeRouter />} errorElement={<ErrorPage />} /> </Routes> </BrowserRouter> </React.StrictMode>, )
export default function Router() { const form = useForm() return (<Routes> <Route path="/" element={<HogeForm {...form} />} errorElement={<ErrorPage />} /> <Route path="/result" element={<HogeResult formValues={form.formValues} />} errorElement={<ErrorPage />} /> </Routes>) }
上記コード例の様にトップレベルで定義している /hoge
というパスは子ルートを持っています。
子ルートは /hoge/result
というパスです。
/hoge
ではHogeForm
というコンポーネントがレンダリングされ、/hoge/result
ではHogeResult
というコンポーネントがレンダリングされる想定だったのですが、これでは上手く動きません。
なぜかというとreact-router v6 ではexact
propsが廃止されデフォルトが完全一致になってしまっているからです。
この影響についてはドキュメントにも記載されています。
is gone. Instead, routes with descendant routes (defined in other components) use a trailing * in their path to indicate they match deeply 出典元:react-router 公式ドキュメント
ちょうどv5からのマイグレーションガイドに記載されていました。
デフォルトが完全一致となったため、そのコンポーネントの中に子ルートがある場合は親ルートのパスに /*
を指定してあげて、その下階層にも一致するパスがあることを教えてあげます。
なので掲載したコード例の以下の部分に
path="/hoge"
/*
を付けてあげて
path="/hoge/*"
とすると、/hoge/result
が見つかり、HogeResult
コンポーネントがレンダリングされるようになります。
めでたし