LoginSignup
17
11

More than 3 years have passed since last update.

React Router v6 の Object-based Routes をキメると、ルーティング実装が気持ちよくなる(かもしれない)ので紹介させてほしい

Last updated at Posted at 2020-08-20

React Router v6(20200820時点では6.0.0-beta.0でpre-release) には新機能として Object-based Routes が追加される。試しに使ってみたところ気に入ってしまったのでぜひ紹介させてほしい。コンポーネントとルーティングをいい感じに分離できてなかなか気持ちが良かった。

概要

  • 「ルーティング用のオブジェクトを作成し、それをuseRoutes hooksでコンポーネントに読み込む」という形でルーティングを実現。
  • 「ルーティング用のオブジェクト」でchildrenを設定することで、ネストの深いルーティングも1つのオブジェクトで表現可能。
  • childrenは親コンポーネント内で<Outlet />コンポーネントとして呼び出し可能で、他のコンポーネントと組み合わせての利用も可能。

コード例

上の説明だけだと伝わる気がしないのでコード例を示す。
特に「親コンポーネント」「子コンポーネント」に、<Route><Switch>(v6では<Routes>)といった「ルーティングに関わるコード」がほとんど存在しない点に注目してほしい。

詳細は公式サイトを参照のこと。
https://reacttraining.com/blog/react-router-v6-pre/#object-based-routes

なお以下のコードは必要な箇所を部分的に抜き出したものであり、そのままでは動作しない。(例えばReact Routerに関係ないimportは全て省略している)
動作するコードは以下リポジトリ参照。(本記事と関係のないコードも多数含まれる点に注意)
https://github.com/takahiromasui001/zaik/tree/00ed024c4f36218a004280adc25316bbc55dbdab

ルーティング用のオブジェクト

ルーティングの情報をコンポーネントからほぼ完全に分離できる。別ファイルにすると更に爽快感が増す。

routes.tsx
import { Navigate } from 'react-router-dom'

export const rootPath = [
  { path: '/login', element: <Login /> },
  {
    path: '/*',
    element: <Private />,
    children: [
      {
        path: 'stocks/*',
        element: <Stock />,
        children: [
          { path: '/:id', element: <StockDetail /> },
          { path: '/', element: <StockList /> },
        ],
      },
      { path: '/', element: <Navigate to="/stocks" /> },
    ],
  },
]

なおこの例ではchildrenを利用することで、ネスト構造を1つのオブジェクトにまとめているが、オブジェクトに分けて必要なコンポーネントに個別に読み込ませることもできる。(その場合は後ほど紹介する<Outlet>を用いず、次に紹介する「親コンポーネント」の実装のみでネスト構造のルーティングを実現することも可能)

親コンポーネント

「ルーティング用のオブジェクト」をimportしてuseRoutesに渡すと、ルーティング機能を持つelement(ReactElement)を作成してくれる。elementをreturnに埋め込むだけでルーティングが実現できる。

App.tsx
import { rootPath } from './routes'

function App() {
  const element = useRoutes(rootPath)

  return  (
    {element}
  )
}

子コンポーネント

「ルーティング用のオブジェクト」においてchildrenとして設定したルーティングは、親コンポーネント内で<Outlet />を呼び出すことで利用可能。<Outlet />はコンポーネントとして扱えるので、他のコンポーネント(下の例で言うとHeader)と組み合わせて利用出来てとても便利。

Private.tsx
import { Outlet } from 'react-router-dom'

const Private: React.FC = () => {
  return (
    <>
      <Header />
      <Outlet />
    </>
  )
}

デメリット

機能を知らないと、最初に各コンポーネントで<Outlet />を見た際にルーティングのことだとは全く分からないし、コンポーネントだけを上から辿っても(routes.tsxを見ない限り)ルーティングの情報に行き着けない。コードの可読性が別の観点で落ちているかもしれない。

最後に

最初にも書いたがまだβ版なので注意して利用のこと。
また、ドキュメントを見ながらサラッと実装して動いて喜んでいるだけなので、おかしな点があったら指摘してほしい。
あとNext.js(触ったことない)のpagesを用いた自動生成(?)ルーティングと使い勝手を比較したい。

参考ページ

17
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
11