React学習備忘録④〜Router〜

# React Router
・アクセスするURLと表示する画面の紐付けを行うライブラリ

まず
```
npx create-react-app --template typescript react-router
```
でプロジェクトを作成し、
```
npm i react-router-dom @types/react-router-dom
```
でReact Routerを使えるようにしておく。

#　基本的なルート定義
```App.tsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { Fuga } from "./components/Fuga";
import { Hoge } from "./components/Hoge";
import { Home } from "./components/Home";
import { NotFound } from "./components/NotFound";

function App() {
  return (
    <>
      <BrowserRouter>
        <Routes>
          {/** 
           * v5では部分的に一致すればそのコンポーネントを返してたためexactが必要だったが、
           * v6では完全一致が必要になったため不要に
          */}
          <Route path="" element={<Home />} />
          <Route path="hoge" element={<Hoge />} />
          <Route path="fuga" element={<Fuga />} />
          {/** 
           * 最後にワイルドカードを使用することで、
           * コンポーネントを返してないルートに対しNotFoundを返すことができる
           */}
          <Route path="*" element={<NotFound />} />
        </Routes>
      </BrowserRouter>
    </>
  );
}

export default App;
```

# ネストしたルート定義
Routeタグの中にRouteを定義することで、ネスト状態のpathをまとめて定義できる。
また途中まで同じパスのルートを配列で定義して、Routeタグの中で回すことができる。
```UserRoute.tsx
import { UserIndex } from "../components/User/UserIndex";
import { UserCreate } from "../components/User/UserCreate";

export const UserRouter = [
    {
        path: 'index',
        element: <UserIndex />
    },
    {
        path: 'create',
        element: <UserCreate />
    }
];
```

```Route.tsx
import { Route, Routes } from "react-router-dom"
import { NotFound } from "../components/NotFound";
import { UserRouter } from "./UserRoute";

export const Router = () => {
    return (
        <>
            <Routes>
                <Route path='users'>
                    {
                        UserRouter.map((route) => (
                            <Route key={route.path}
                                path={route.path}
                                element={route.element}
                            />
                        ))
                    }
                </Route>
                {/**
                 * V5だと*のNotFound定義はネストしたものに対応できずRouteタグ内に書く必要があったが、
                 * V6は対応可能となった（users/hogeみたいなものでもNotFoundを返す）
                 */}
                <Route path="*" element={<NotFound />} />
            </Routes>
        </>
    )
}
```

# クエリパラメータを利用したルート定義
```Query.tsx
import { useLocation } from "react-router-dom"

export const Query = () => {
    /**
     * useLocation()の中にはpathnameやkey,stateなどが入っている
     * その中にsearchというのがあり、そこにurlの?以降が入っている
     */
    const { search } = useLocation()
    //クエリパラメータに関する便利メソッドができる
    const query = new URLSearchParams(search)
    return (
        <>
            <div>idクエリ {query.get('id')}</div>
            <div>nameクエリ {query.get('name')}</div>
        </>
    );

}
```
```Route.tsx
import { Route, Routes } from "react-router-dom"
import { NotFound } from "../components/NotFound";
import { Query } from "../components/Query";

export const Router = () => {
    return (
        <>
            <Routes>
                <Route path="/query" element={<Query />} />
                <Route path="*" element={<NotFound />} />

            </Routes>
        </>
    )
}
```

# URLパラメータを利用したルート定義
```Url.tsx
import { useParams } from "react-router-dom";

export const Url = () => {
    /**
     * useParams()でパラメータ部分を取得
     * Router定義で/:paramaterとなっているのがuseParamsのなかに入る
     */
    const { paramater } = useParams();
    return (
        <>
            {/**
             * url/sampleと入力することで、
             * パラメータ sampleと出力される
             */}
            <p>パラメータ {paramater}</p>

        </>
    )
}
```
```Route.tsx
import { Route, Routes } from "react-router-dom"
import { NotFound } from "../components/NotFound";
import { Url } from "../components/Url";

export const Router = () => {
    return (
        <>
            <Routes>
                {/**
                 * :がURLパラメータ部分
                 */}
                <Route path="/url/:paramater" element={<Url />} />
                {/**
                 * urlだけだとNotFoundが返される
                 */}
                <Route path="*" element={<NotFound />} />

            </Routes>
        </>
    )
}
```

#画面からの遷移
・Lintタグで囲う(aタグに近いもの)
・useNavigateの使用
```Home.tsx
import { FC, memo } from "react";
import { useNavigate } from "react-router-dom";
import { Link } from "react-router-dom";

export const Home: FC = memo(() => {
    const navigate = useNavigate()
    /**
     * navigate()で行きたいパスを指定
     */
    const onClickHoge = () => navigate('/hoge')
    /**
     * 値を入れることで、その値の分だけ戻る/進むことができる
     */
    const onClickPrev = () => navigate(-1)
    const onClickNext = () => navigate(+1)
    return (
        <>
            Homeのページ
            <Link to='/hoge' >hoge</Link>
            <Link to='/fuga' >fuga</Link>
            <button onClick={onClickPrev}>前へ</button>
            <button onClick={onClickNext}>次へ</button>
            <button onClick={onClickHoge} >hogeへ遷移</button>
        </>
    );
});
```

前回：[CSSについて](https://qiita.com/_takenoko/items/e1e5b49d328e95c62338)
次回：グローバルstateの管理について