この記事ではReact Routerを使ったルーティングの設定方法をReact学習中の方向けに解説します。

ルーティングは複数のページがあるReactアプリケーションを作成する際に必要な作業であり、Reactを学習する上で避けて通れません。

以下の内容を解説するので、React学習中の方はぜひ参考にしてください!

  • React Routerとは何か?ルーティングとは何か?
  • React Routerの基本的な使い方

React Routerとは?

React Routerとは?
(参照:https://reactrouter.com/

React RouterはReactでSPAを構築する時に有効なライブラリです。

ReactでSPA を構築する時、DOM操作による書き換えで複数ページがあるように見えますが、URLは同一のためブラウザからは1つのページとして認識されてしまいます。

React Routerはページ毎に構成されているコンポーネントとURLを紐づける役割を担います、つまり、画面状態とURLを紐づけて履歴を同期し、疑似的にページ遷移することでSPAの画面状況に応じてブラウザからアクセスするURLが複数存在することを可能にしているのです。

React Routerの使い方

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開発をするための環境構築の手順 | 初心者でもわかるように解説」の記事をご覧ください。

ルーティングの設定・定義

プロジェクトに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キーパーアプリが構築できますのでぜひチャレンジしてみてください。