【React】React Router-v6でルーティングを設定する

# はじめに
本記事ではReact Routerを使ったルーティングの設定方法について紹介します。
手動でパスを切り替えることによる画面遷移、`<Link>`コンポーネント、`useNavigate`フックを利用し画面遷移を行います。

# 対象の方
- React Routerを使ったルーティングの設定方法について知りたい方
- タイトルが気になった方

# 環境
- Vite: 5.0.8
- Raect：18.2
- typescript：5.2.2
- react-router-dom:6.22


# react-router-domのインストール
次のコマンドでパッケージをインストール。
```
npm install react-router-dom
```
https://www.npmjs.com/package/react-router-dom

https://reactrouter.com/en/main

# ルーティングを設定するページの作成

以下の`sample.tsx`を例に、
遷移するページごとにコンポーネントを作成します。
今回は`sample.tsx`、`About.tsx`、`Home.tsx`、`Info.tsx`の4つのコンポーネントを準備しておきます。

```tsx:sample.tsx
const Sample = () => {
  return (
    <main>
      <h1>サンプルページ</h1>
      <p>hogehogehoge</p>
    </main>
  )
}

export default Sample
```
<details><summary>App.css</summary>


```css:App.css
body {
  padding: 0;
  margin: 0;
  font-size: 2rem;
}

main {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
```
</details>

# ルーティング設定

`main.tsx`において、Appコンポーネントを`BrowserRouter`でラップします。

```tsx:main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import { BrowserRouter } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
)
```

`Routes`、`Route`を使用しそれぞれのパスで表示するコンポーネントを指定しています。

```tsx:App.tsx
import { Routes, Route } from 'react-router-dom'

import Home from './components/Home'
import About from './components/About'
import Info from './components/Info'
import Sample from './components/Sample'
import NotFound from './components/NotFound'

import './App.css'

const App = () => {
  return (
    <Routes>
      <Route path='/' element={<Home/>} />
      <Route path='/About' element={<About/>} />
      <Route path='/Info' element={<Info/>} />
      <Route path='/Sample' element={<Sample/>} />
    </Routes>
  )
}

export default App
```
ここまで出来たらプロジェクトを起動し、
ブラウザのパスを変更しページの遷移を確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/50226021-dfee-1b81-cbc1-6432bf211a57.png)


# 404エラーページの作成
上記の`App.tsx`では4つのパス（/、/About、/Info、/Sample）を指定していますが、
それ以外のパスにアクセスすると何も表示されません。
よってどのパスにもマッチしない場合に表示される 404 エラーページを作成しておきます。

```tsx:NotFound.tsx
const NotFound = () => {
  return (
    <main>
      <h1>404</h1>
      <h1>存在しないページです</h1>
    </main>
  )
}
  
export default NotFound
```

以下のように、`path='*'`をしてすることで、
どのパスにもマッチしない場合に表示されるページを指定しておきます。

```tsx:App.tsx
import NotFound from './components/NotFound'

{/* 省略 */}

<Routes>
  {/* 省略 */}
  <Route path='*' element={<NotFound/>} />
</Routes>
```

# Linkコンポーネントによるページ遷移

Linkコンポーネントを使用し異なるパスへの画面遷移を実装します。
`to`プロパティにリンク先のパスを指定します。
ユーザーがリンクをクリックすると、指定したパスへの画面遷移が行われます。

```tsx:Home.tsx
import {Link } from 'react-router-dom'

const Home = () => {
  return (
    <main>
      <h1>ホームページ</h1>
      <p>hogehogehoge</p>
      <Link to='/'>Home</Link>
      <Link to='Sample'>Sample</Link>
      <Link to='About'>About</Link>
      <Link to='Info'>Info</Link>
    </main>
  )
}

export default Home
```

起動すると4つリンクが表示されている事が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/4f4413e0-a539-c55e-90cc-c0f3e81ff24e.png)

# useNavigateを利用した画面遷移
React Router の useNavigate フックを使用してプログラム内でのページ遷移を実装します。
各ボタンのクリックイベントで、指定したパスの画面に遷移します。

```tsx:Home.tsx
import {useNavigate } from 'react-router-dom'

const Home = () => {
  const navigate = useNavigate();

  return (
    <main>
      <h1>ホームページ</h1>
      <p>hogehogehoge</p>
      <button onClick={() => { navigate('Sample')}}>サンプルページ</button>
      <button onClick={() => { navigate('About')}}>Aboutページ</button>
      <button onClick={() => { navigate('Info')}}>Infoページ</button>
    </main>
  )
}

export default Home
```

起動すると各ページに遷移するが表示されている事が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/d78944c9-a65d-a907-43b3-1b4eadd7e129.png)



# 参考

https://reactrouter.com/en/main

https://reactrouter.com/en/main/hooks/use-navigate