この記事ではReact Routerを使ったルーティングの設定方法をReact学習中の方向けに解説します。
ルーティングは複数のページがあるReactアプリケーションを作成する際に必要な作業であり、Reactを学習する上で避けて通れません。
以下の内容を解説するので、React学習中の方はぜひ参考にしてください!
- React Routerとは何か?ルーティングとは何か?
- React Routerの基本的な使い方
React Routerとは?
React RouterはReactでSPAを構築する時に有効なライブラリです。
ReactでSPA を構築する時、DOM操作による書き換えで複数ページがあるように見えますが、URLは同一のためブラウザからは1つのページとして認識されてしまいます。
React Routerはページ毎に構成されているコンポーネントとURLを紐づける役割を担います、つまり、画面状態とURLを紐づけて履歴を同期し、疑似的にページ遷移することでSPAの画面状況に応じてブラウザからアクセスするURLが複数存在することを可能にしているのです。
React Routerの使い方
ここからはReact Routerを初めて設定する人向けに、インストール方法、設定・定義などについて説明します。
React Routerのインストール
React RouterはWeb開発専用のreact-router-domをインストールするだけで使用可能です。
まずはコマンドライン(ターミナル)でReact RouterをインストールしたいReactプロジェクトのディレクトリに移動し、以下のコマンドを実行してください。
npm install react-router-dom
インストールが完了したら、以下のコマンドを実行して動作しているか確認します。
npx start
ブラウザが起動し、下の画面が表示されれば問題なくインストールができています。
なお、Reactプロジェクトの作成方法が分からないという方は「React開発をするための環境構築の手順 | 初心者でもわかるように解説」の記事をご覧ください。
ルーティングの設定・定義
プロジェクトにReact Routerをインストールしたらいよいよルーティングを設定していきます。今回はBrowserRouterとReact Routerの公式ドキュメント(v6)を基に前項で作成したプロジェクトを使用します。
React Routerは要素ツリーのRouteまたはその近くにRouter要素をレンダリングすることで機能するため、React Routerから関連のコンポーネントをインポートします。
ここで今回インポートするコンポーネントを解説します。
1)BrowserRouter
React Router が提供しているプロバイダーコンポーネントの1つ。HTML の History API(pushState、replaceState、popstate イベント)を使用して UI を URL と同期させるルーターで、一般的な SPA 開発で多く使われています。
プロジェクトで1回しか使えないため、基本的に最上層へ配置。react-router関連のコンポーネントは全て<BrowserRouter>から</BorwserRouter>の中に記述する必要があります。
2)Route
ルーティング先のURLと表示したいコンポーネントを指定します。ちなみにRoutesコンポーネントは複数のRouteコンポーネントを中に記述できます。
3)Link
HTMLの<a></a>と同じ要素。<Link to=””></Link>でリンク先を指定することでそこへ遷移できます。
では、実際にコードを見ていきましょう。まず、src/index.jsを以下のように書き換えます。
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import './index.css';
import App from './App';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
これで、src/index.jsがsrc/app.jsに記述してあるAppコンポーネントを<BrowserRouter>から</BorwserRouter>で囲み、React Routerを使う準備ができました。
続いて、src/app.jsを以下のように書き換え、Routeをツリー状にしてルーティングを定義します。
import * as React from "react";
import { Routes, Route, Link } from "react-router-dom";
import "./App.css";
function App() {
return (
<div className="App">
<h1>Welcome to React Router!</h1>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}
Routes、Route、Linkをインポートし、Appコンポーネント内に「path」でルーティング先のURL、「element」で表示したいコンポーネントを指定しました。
さらにsrc/app.jsにHomeコンポーネントとAboutコンポーネントを作成します。ちなみにリンク先の設定は<Link to=”遷移先”>表示する文字列</Link>と記述。今回は相互遷移できるようそれぞれリンク先を設定しています。
// App.js
function Home() {
return (
<>
<main>
<h2>Welcome to the homepage!</h2>
<p>You can do this, I believe in you.</p>
</main>
<nav>
<Link to="/about">About</Link>
</nav>
</>
);
}
function About() {
return (
<>
<main>
<h2>Who are we?</h2>
<p>
That feels like an existential question, don't you
think?
</p>
</main>
<nav>
<Link to="/">Home</Link>
</nav>
</>
);
}
これで以下の画像の通り、localhost:3000はHomeコンポーネントが、localhost:3000/aboutはAboutコンポーネントが表示され、リンクで遷移できるようになりました。
今回はふれませんでしたが、現在推奨されているルーティングの定義方法は、それぞれのルートを定義したRouteコンポーネントをSwitchコンポーネントで囲む、という記述です。これはSwitchコンポーネントには現在のURLと一致するRouteを上から順に探し、最初に一致するルートの内容を返すという特徴があるからです。
その他にも、React Routerのドキュメント内のAPIリファレンスにはインポートできるコンポーネントの詳細が記載してあります。一度熟読してみるとより理解が深まるのでオススメです。
## Hooks APIについて
Hooks APIはフック (hook) は React 16.8 で追加された新機能で、stateなどのReact機能がクラスを書かずに使えるようになります。React RouterもHooksに対応しており、以下の4つのフックを提供しています。
- useHistory
- useLocation
- useParams
- useRouteMatch
上記は全てreact-router-domからインポートして利用します。
// 例:useHistoryを利用する場合
import { useHistory } from 'react-router-dom'
次項からは4種類のフックを簡単に解説していきます。
useHistory
useHistoryフックは履歴数(length)や最後に実行されたアクション(PUSH・REPLACE・POP)、locationオブジェクト及び履歴等を持っている「historyオブジェクト」を返します。history APIにアクセスして、push()による遷移やlocationからパス位置の取得が可能です。
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
※https://v5.reactrouter.com/web/api/Hooks/usehistoryより
useLocation
useLocationフックはpathname(URL)、search(クエリパラメータ)、hash(URLハッシュ)、state(ユーザ定義のデータ)を持つ「locationオブジェクト」を返します。現在のパス情報を取得してLinkコンポーネントやhistoryオブジェクトに渡せます。
import React from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Switch,
useLocation
} from "react-router-dom";
function usePageViews() {
let location = useLocation();
React.useEffect(() => {
ga.send(["pageview", location.pathname]);
}, [location]);
}
function App() {
usePageViews();
return <Switch>...</Switch>;
}
ReactDOM.render(
<Router>
<App />
</Router>,
node
);
※https://v5.reactrouter.com/web/api/Hooks/uselocationより
useParams
useParamsフックは、遷移前のmatchオブジェクトのパスパラメータを返します。遷移元のパス情報を遷移先で使用する際に活用します。定義方法は、Routeコンポーネントのpathで:をつけます。
import React from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Switch,
Route,
useParams
} from "react-router-dom";
function BlogPost() {
let { slug } = useParams();
return <div>Now showing post {slug}</div>;
}
ReactDOM.render(
<Router>
<Switch>
<Route exact path="/">
<HomePage />
</Route>
<Route path="/blog/:slug">
<BlogPost />
</Route>
</Switch>
</Router>,
node
);
※https://v5.reactrouter.com/web/api/Hooks/useparamsより
useRouteMatch
useRouteMatchフックは、path(ルートパス)、url(URL)、isExact(URLとルートパスの一致・不一致)、params(パスパラメータ)を持つmatchオブジェクトを返します。パスの条件を元にコンポーネント単位でレンダリングの制御が可能になります。
import { Route } from "react-router-dom";
function BlogPost() {
return (
<Route
path="/blog/:slug"
render={({ match }) => {
// Do whatever you want with the match...
return <div />;
}}
/>
);
}
import { useRouteMatch } from "react-router-dom";
function BlogPost() {
let match = useRouteMatch("/blog/:slug");
return <div />;
}
※https://v5.reactrouter.com/web/api/Hooks/useroutematchより
## まとめ
今回は入門向けにReact Routerの設定について紹介してきました。Reactでルーティングが可能になることで開発の幅が広がり、スピードも上がります。React Routerの公式チュートリアルではBookキーパーアプリが構築できますのでぜひチャレンジしてみてください。