React Routerの備忘録

# はじめに
Reactの学習を始めて1番初めに躓いたルーティングに関する備忘録をまとめます。
初学者ゆえ、記述内容に誤りがある場合はご指摘いただけると幸いです。

# React Routerの基本

## React Routerとは
Reactで作成されたアプリケーションに対して、ページ遷移やURL管理を行うライブラリ。
SPA(シングルページアプリケーション）ではブラウザのURLによって異なるコンポーネント(ページ）を表示させることが重要だが、React Routerを用いることで簡単に実現ができる。

## React Routerの導入方法
1. Reactプロジェクトに追加する必要があるため、以下のコマンドでインストールする。
```terminal:
npm install react-router-dom
```

2. ルーティングのセットアップ
ページの割り振りをするためのルーティングを設定する。
Viteを利用している場合は、main.tsxにルーティングを記載する or 別途ルーティング用のファイルを作成して切り出す。

以下はmain.tsxに直接記載した例。

```tsx:main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Contact from './Contact';

// ルーティングテーブルを作成
const routes = createBrowserRouter(
  createRoutesFromElements(
    <>
      <Route path="/" element={<Home />}></Route>
      <Route path="/about" element={<About/>}></Route>
      <Route path="/contact" element={<Contact />}></Route>
    </>
  )
);

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    // RouterProviderでルーター機能を設定
    <RouterProvider router={routes} />
  </StrictMode>,
)

```
`createBrowserRouter`でルーティングの定義を行う。
`RouterProvider router={ルーティング}`でルーター機能を設定し、配下のコンポーネントはルーティングの定義に基づいて表示されるようになる。
`<Route path="パス" element={コンポーネント} />`でURLにアクセスした際に表示されるコンポーネントを指定できる。

# ルーターが対応したリンクを設定する
1. App.tsxに対して、ナビゲーション対応したリンクを表示させる。

```ts:App.tsx
import { Link, Outlet } from 'react-router-dom';

const App: React.FC = () => {

  return (
    <>
      <ul>
        {/* Linkタグを使用して、ルーティングに対応するリンクを作成 */}
        <li><Link to ="/">Home</Link></li>
        <li><Link to ="/about">About</Link></li>
        <li><Link to ="/contact">Contact</Link></li>
      </ul>
      <Outlet />
    </>
  )
}

export default App

```

`<Link />:`クリックした場合に別のページに移動するリンクを作る。
`<Outlet />:`ルーティングされた子コンポーネントをレンダリングする要素。

2. ルーティングテーブルを修正
```tsx:main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Contact from './Contact';
import App from './App';

// ルーティングテーブルを作成
const routes = createBrowserRouter(
  createRoutesFromElements(
    <Route element={<App />}> //追記
      <Route path="/" element={<Home />}></Route>
      <Route path="/about" element={<About/>}></Route>
      <Route path="/contact" element={<Contact />}></Route>
    </Route>
  )
);

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterProvider router={routes} />
  </StrictMode>,
)

```
※共通で使用するHeaderやFooterはLayout.tsxにまとめておくようにすると良い。

なお、追加したAppをコンポーネントを呼び出すRoute要素には`path=`の記載がない。この要素は他の要素の親ルートになり、子ルートに共通のレイアウト提供するためのレイアウトになるため、**レイアウトルート**と呼ばれる。

## ルーター経由で情報を受け渡しする
### パスの一部をパラメータとして受け取る
Routeに指定したパスの中からパラメータを取得することができる。

1. パスを設定する
ルーティングテーブルでパラメータとして受け渡したい情報を`:名前`の形式で記載する。

```tsx:main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Contact from './Contact';
import App from './App';
import Post from './Post';

// ルーティングテーブルを作成
const routes = createBrowserRouter(
  createRoutesFromElements(
    <Route element={<App />}> //追記
      <Route path="/" element={<Home />}></Route>
      <Route path="/about" element={<About/>}></Route>
      <Route path="/contact" element={<Contact />}></Route>
      <Route path='/posts/:id' element={<Post />}></Route>　 //追記
    </Route>
  )
);

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterProvider router={routes} />
  </StrictMode>,
)
```
上記のようにパスの中に`:名前`と記載することで、/posts/1というようなパスにアクセスされた場合は1の値をidとして受け渡すことができる。
このようにパラメーターの値をパスの一部として表現するパラメーターのことを**ルートパラメーター**と呼ぶ。

2\. リンクにもパスを設定する
Link要素のpathに受け渡したい値を指定する。以下のケースだと12345をパラメーターとして渡す。
```tsx:App.tsx
import { Link, Outlet } from 'react-router-dom';

const App: React.FC = () => {

  return (
    <>
      <ul>
        {/* Linkタグを使用して、ルーティングに対応するリンクを作成 */}
        <li><Link to ="/">Home</Link></li>
        <li><Link to ="/about">About</Link></li>
        <li><Link to ="/contact">Contact</Link></li>
        <li><Link to ="/posts/12345">投稿ページ</Link></li> //追記
      </ul>
      <Outlet />
    </>
  )
}

export default App
```

3\. ルートパラメーターを受け取る

```tsx:Post.tsx
import { useParams } from 'react-router-dom';

const Post: React.FC = () => {
  const { id } = useParams<{id: string}>();

  return(
    <div>
      <h1>これはPost{id}のページです</h1>
    </div>
  )
}

export default Post;
```

`usePrams()`を使用して、現在のURLからルートパラメーターをキー:バリュー型のオブジェクトで取得する。今回はidを文字列として取得するため、`const { id } = useParams<{id: string}>();`と定義している。


# 参考サイト
https://reactrouter.com/en/main