ページを切り替えるためには、ルーティングを行う必要があります。
ここではReactRouterをインストールして、ルーティングのコードを書きます!
ReactRouterとは?
React Router はシンプルで宣言的なルーティング ライブラリとして使用できます。その役割は、URL をコンポーネントのセットにマッチングさせ、URL データへのアクセスを提供し、アプリ内をナビゲートすることだけです。
ちょっとわかりづらいですが、ページコンポーネントとURLのパスをワンセットにして、簡単にそのページにアクセスできるようにするってことですね!
公式ドキュメントはこちら。
実装中のコードを見てみよう
現在のコードを見てみましょう。
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Register } from "./components/Register";
import { Login } from "./components/Login";
import { MyPage } from "./components/MyPage";
import "./App.css";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path='register' element={<Register />} />
<Route path='login' element={<Login />} />
<Route path='/' element={<MyPage />} />
</Routes>
</BrowserRouter>
);
}
export default App;
ページコンポーネントが増えたり、ネストするルーティングがあった際に、コードを変更する予定です。
コードを書く手順は以下の通りです。
- <BrowserRouter>でアプリ全体を囲む
- <Routes>でルーティングしたい要素である<Route… />を囲む
- <Route />の中に、pathとelementを渡す
さて、実際のURLはどうなるのでしょうか?
例えばRegisterコンポーネントだと、http://localhost:5173/register/のような形になります。
複雑なルーティングの例
<Routes>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route element={<AuthLayout />}> <----------ポイント①
<Route path="login" element={<Login />} /> <----------ポイント②
<Route path="register" element={<Register />} />
</Route> <----------ポイント③
<Route path="concerts">
<Route index element={<ConcertsHome />} /> <----------ポイント④
<Route path=":city" element={<City />} /> <----------ポイント⑤
<Route path="trending" element={<Trending />} />
</Route>
</Routes>
こちらは公式サイトで掲載されているコード例です。ポイントを確認しましょう!
【ポイント①】レイアウトルート
<Route element={<AuthLayout />}> <----------ポイント①
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
</Route>
このルートには「path」が指定されていません。
「path」を指定しないことでURL構造を変えずに、レイアウトだけ適用できるわけです。
<AuthLayout />は、機能を持つのではなく、ページのレイアウトを決めるコンポーネントです。
ヘッダー、コンテンツ、フッターのようなコンポーネントを含むことで自由にレイアウトを組むことができます。
【ポイント②】ネストされた子ルート
<Route element={<AuthLayout />}>
<Route path="login" element={<Login />} /> <----------ポイント②
<Route path="register" element={<Register />} />
</Route>
<AuthLayout />の中に<Login />をネスト化しています。
この時、<AuthLayout />が親ルート、<Login />が子ルートと呼ばれます。
しかしこのコードだけではブラウザには表示されません!なぜでしょうか?
「親コンポーネントで<Outlet />をリターンしていないから」です。
//AuthLayout.tsx(親ルート)
import { Outlet } from "react-router";
export const AuthLayout () => {
return (
<div>
<h1>AuthLayout</h1>
<Outlet /> <----------これが絶対必要!!
</div>
);
}
詳しくは以前こちらの記事でまとめていますので、お時間が許しましたらご覧ください。
【ポイント③】ネスト時の書き方に注意
<Route element={<AuthLayout />}>
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
</Route> <----------ポイント③
親ルートは子ルートを囲まないといけないので、閉じタグ(タグって言い方じゃないかも)が必要です。
親と子で書き方が若干違うので、注意しましょう!
【ポイント④】インデックスルート
<Route path="concerts">
<Route index element={<ConcertsHome />} /> <----------ポイント④
<Route path=":city" element={<City />} />
<Route path="trending" element={<Trending />} />
</Route>
「index」とは一体何なのでしょう?
pathをindexにすると、親のURLでもって、親の<Outlet />にレンダリングされます。
ただし、インデックスルートは子ルートを持つことができない点に注意です!
<Route path="concerts">
<Route index element={<ConcertsHome />} >
<Route path="child" element={<Child />}/> <----------これはできない!!
</Route>
<Route path=":city" element={<City />} />
<Route path="trending" element={<Trending />} />
</Route>
【ポイント⑤】動的セグメント
<Route path="concerts">
<Route index element={<ConcertsHome />} />
<Route path="cities:city" element={<City />} /> <----------ポイント⑤
<Route path="trending" element={<Trending />} />
</Route>
私個人的にはこのポイントの理解が難易度高かったです!
pathの「:city」ですが、コロンが付いてますよね。
例えばユーザーが手入力でhttp://localhost:5173/concerts/cities/osakaと検索バーに入力すると、「:city」に対応する「osaka」というパラメータをuseParamsで取得することができます。
http://localhost:5173/concerts/cities/tokyoはどうでしょう?そうです、tokyoを取得できます。
実際にどう使うのかについては、以下のコードをご参照ください。
import { useParams } from "react-router";
export const Cities () => {
const params = useParams();
return <h1>City: {params.city}</h1>;
}
こちらのコードだと、Citiesコンポーネントのh1タグで「City: osaka」と動的に表示させることが可能です。
この時、http://localhost:5173/concerts/cities/osakaは、ルーターの「cities:city」とマッチすると言うのだそう。
余談ですが…
上記の他にもまだまだ話したいことはありますが、長くなるので今日はここまで!
気になる方は公式サイトをご覧くださいね。
余談ですが、Reactコンポーネントの概念について、今までしっくりきていなかったのです。
個人開発をして色々調べているうちに、以前Udemyで学習した内容などを思い出しました。
コンポーネントは「機能単位で作る」と思い込んでいたばかりに、ページレイアウトを作成できたり、カスタムフックを自作する場合に使ったりできることを忘れていました。今回再確認できました。
リファクタリングする際にディレクトリの分け方などをわかりやすく工夫するのが良さそうです!
- 機能を作るコンポーネント
- ルーティングに必要なページを作るコンポーネント
- カスタムフックを作るコンポーネント
- ページをレイアウトするコンポーネント
- ルーティングだけをまとめたコンポーネント
解釈を間違えている点もあるかもしれませんが、何となく頭の中でイメージできると理解も深まります!
間違えていた場合は、またどこかのタイミングで自分を更新できたらと思います。
今回も最後までお読みいただき、ありがとうございました。
コメント