かんたんにクライアントサイドルーティングを試してみる 前編

## はじめに
[こちらの記事](https://qiita.com/course_k/items/cbb80d376721d6c543ac)で少し触れたreact-routerについて、基礎的なところから改めてまとめてみます。

業務で使ってはいるものの、よくわからないまま使っているので、ちゃんと自分の血肉とできるようにします。

## そもそもクライアントサイドルーティングとは
普段インターネットでwebページを閲覧する場合、「このページください」とサーバーにリクエストして、サーバーが該当ページのhtmlを返してくれるという仕組みで成り立っています。
これがサーバーサイドルーティングです。

サーバーから新しくページを取得してそれを表示するので、新たに色々読み込む処理が発生します。

一方、クライアントサイドルーティングは、上記の動きをしません。
あるページのリンクにアクセスされた場合、新しくhtmlを取得することなく、表示しているページのまま、Reactの処理によって新しいページが取得されたかのような動きをします。

新しく諸々を読み込む必要がないので、サクサク動くというのがメリットのようです。

## まずは環境構築
Node.jsが導入されていることと、VS Codeが導入されていることが前提となります。
また、使用しているPCのOSはMacになります。

:::note warn
色々実施していますが、react-router-domをインストールすれば、クライアントサイドルーティングを実行するための環境構築は完了です。
:::

任意のフォルダで以下のコマンドを実行します。
今回のReactの実行環境はviteで作成します。
```bash
npm create vite
```

プロジェクト名と、何の言語を使うか聞かれるので今回は以下の通り設定します。
ReactとTypeScriptの組み合わせで作っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/1f70f2af-499f-e5ea-e2cd-2a630e99c038.png)

完了したら、作成したプロジェクトに移動して、React Routerをインストールします。
このReact Routerがクライアントサイドルーティングのために必要なモジュールです。
```bash
cd [作成したプロジェクト]
npm install react-router-dom
```
少し時間を置くと、以下のように完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/caf6561d-23a2-1fe6-898a-60a11d23aadc.png)

インストールが完了したらVS Codeで作成したプロジェクトを開きます。
VS Codeのターミナルから以下のコマンドを実行してアプリを立ち上げます。

```bash
npm run dev
```
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/197baa42-e287-c5cf-7a87-0b4c09c0a4c8.png'>

以下のように表示が変わるので、LocalのURLにアクセスします。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/3eee7919-2507-0044-3bfa-f8697b967ec5.png'>

以下のような画面が表示されれば、準備完了です。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/16e6e21f-d98f-b463-fb74-604488087e7b.png'>

## 基本のルーティング
まずは基礎的なルーティング方法について確認します。

### 事前準備
コンポーネントを2つ用意します。
まずはTOP画面用です。
```react:TopComponent.tsx
import { Link } from "react-router-dom";

const TopComponent = () => {
  return (
    <>
      <h1>Top画面</h1>
      <Link to="another">別の画面へ</Link>
    </>
  );
};

export default TopComponent;
```
ポイントはReactRouterの`Link`コンポーネントを使っているところです。

このコンポーネントを使用すると、`a`タグが生成されます。
そして、`to`属性に指定した値が`href`属性に設定されます。

ただし、通常の`a`タグとは挙動が異なり、ページ全体の再読み込みをしません。

次に遷移先の別画面を用意します。
```react:AnotherComponent.tsx
const AnotherComponent = () => {
  return (
    <>
      <h1>別の画面</h1>
    </>
  );
};
export default AnotherComponent;
```
これはただの表示用なので特にポイントはありません。

### ルーティング処理
既存の`main.tsx`の処理を以下のように書き換えます。
```react:main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import {
  RouteObject,
  RouterProvider,
  createBrowserRouter,
} from "react-router-dom";
import TopComponent from "./TopComponents.tsx";
import AnotherComponent from "./AnotherComponent.tsx";
const routes: RouteObject[] = [
  {
    path: "/",
    element: <TopComponent />,
  },
  {
    path: "/another",
    element: <AnotherComponent />,
  },
];
const router = createBrowserRouter(routes);
ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);
```

ポイントは3つです。

#### 1. ルーティング用情報の生成
`routes`のようなルーティング情報を設定したオブジェクトの配列を作ります。
オブジェクトのプロパティには様々なものが設定できます。
基本としては「path」と「element」の2つがあれば十分です。
「path」は遷移させたいパスを、
「element」は「path」にアクセスされたとき表示させたい要素を指定します。

#### 2. Routerオブジェクトの生成
ルーティング情報を`createBrowserRouter`の引数に設定することで、Routerオブジェクトを取得できます。

#### 3. RouterProviderコンポーネントの使用
このコンポーネントのpropsに生成したRouterオブジェクトを渡します。

これで、基本のルーティング処理は完了です。

### 挙動の確認
実際の動きを見てみましょう。

ルートパスでは、TOP画面が表示されます。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/cb7b717c-222e-f28c-84b6-b4494ac0d070.png'>

リンクをクリックしてみましょう。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/3a7162df-1c4b-9c7d-fc2a-1292bd132f56.png'>

サーバーサイドの処理は何も書いていませんが、別画面を表示することができました。
また、開発者モードを起動して、ネットワークタブを開いてもらうとわかるのですが、この遷移のとき、新しい情報が読み込まれていないのがわかります。
（画面キャプチャで確認するのは難しいので、省略します。）

これが、基本のルーティングです。

## まとめ
今回は基本的なルーティングのみにとどめて、ReactRouterの使い方を確認しました。
普段私がやっている方法とは違っていたので、やはり基礎を押さえることが大事だな、と思いました。
（とくに`Link`コンポーネントの部分）

次回（明日）は更にいろいろなことに挑戦してみます。