はじめに
ReactとReact Routerで、以下のようなナビゲーションバーを作成したときのメモです。
この記事では、はじめにReact Routerの各種コンポーネントの概要について触れています。その後、サンプルコードを掲載しています。サンプルはWebアプリケーションであることを前提としています。React Native については一切触れていません。
使用しているライブラリとバージョンは以下のようになっています。v3以前のReact Routerだと存在しない機能にも触れているので注意してください。
パッケージ名 | バージョン |
---|---|
react | 16.4.2 |
react-dom | 16.4.2 |
react-router-dom | 4.3.1 |
React Router
ルーティングのための各種機能を提供するライブラリです。ルーティングにより、URLとコンポーネントを対応づけられます。ブラウザ等でURLが指定されると、対応するコンポーネントを表示してくれるようになります。これにより、SPAなアプリケーションの状態を、ブラウザの履歴として保存できるようになります。また、特定のページにURLを指定して直接アクセスできるようになります。React Routerの機能はすべてReactのコンポーネントとして提供されています。
パッケージ
react-router
というパッケージが存在しますが、これを直接インストールする必要はありません。代わりに react-router-dom
もしくは react-router-native
を、自分の開発するアプリケーションに合わせてインストールします。
- react-router-dom: Webアプリ
- react-router-native: iOSやAndroidといったネイティブアプリ
今回はWebアプリなので、react-router-dom をインストールします。
$ yarn add react-router-dom
Routerコンポーネント
役割に応じたRouterがいくつかあります。まずは、どのRouterを使用するか決める必要があります。Webアプリ向けには、BrowserRouter と HashRouter が提供されています。ネイティブアプリであれば、NativeRouter があります。
BrowserRouter と HashRouter は、生成するURLに若干違いがあります。また、BrowserRouterはHTML5の history API をサポートしているブラウザで使用可能です。レガシーなブラウザをサポートしたい場合はHashRouterを利用します。また、公式ドキュメントには静的ファイルだけを提供するような場合も HashRouter が良いと書かれています。
Generally speaking, you should use a <BrowserRouter> if you have a server that responds to requests and a <HashRouter> if you are using a static file server. 公式ドキュメント - Routers
この記事ではひとまず BrowserRouter を使うことにします。
Routeコンポーネント
ルーティングを定義します。以下のように「どのパスでどのコンポーネントをレンダリングするか」をRouteコンポーネントのpropsに指定します。
<BrowserRouter> <Route path="/" component={IndexPath} /> <Route path="/path2" component={Path2} /> </BrowserRouter>
上の例では、URLが /
の場合に <IndexPath /> がレンダリングされます。/path2
の場合は、 <IndexPath /> と <Path2 /> の両方がレンダリングされます。これは、前方一致でマッチングするすべてのコンポーネントをレンダリングするためです。したがって、/
で始まるすべてのURLで <IndexPath /> がレンダリングされます。
この振る舞いが便利なこともありますが、困る場合もあります。完全一致した時のみレンダリングさせたい場合は、exact
を指定します。これで、/
では <IndexPath /> 、 /path2
では <Path2 /> がレンダリングされるようになります。
<BrowserRouter> <Route exact path="/" component={IndexPath} /> <Route path="/path2" component{Path2} /> </BrowserRouter>
NavLinkコンポーネント
リンクを生成できるコンポーネントには、 Link と NavLink があります。ナビゲーションバーを作るにあたっては、NavLinkのほうが都合がいいです。NavLinkは、「リンクのURLと現在のURLが同じ場合に見た目を変える」ということが簡単に実現できます。下記のように、activeClassName
や activeStyle
に値を指定するだけです。
<NavLink to='/test' className='test' style={{fontSize: '1rem'}} activeClassName='active' activeStyle={{color: 'red'}} />
レンダリングされると以下のようになります。className や style が元から指定されている場合は、それに追加される形でレンダリングされます。
<!-- /test にいる場合 --> <a href="/test" class="test active" style="font-size: 1rem; color: red;" /> <!-- /test 以外にいる場合 --> <a href="/test" class="test" />
activeClassName や activeStyle はルーティングと同様に前方一致で有効となります。BrowserRouterと同様に exact を指定することで、完全一致のときのみ有効にさせることができます。
自分で頑張って処理を書けば Link でも同じことを実現できますが、少ないコードで書けるのであればそれに越したことはありません。ということで今回は NavLink を使います。
ナビゲーションバーの作成
react-router-domのBrowserRouter, Route, NavLinkの3つのコンポーネントを使って、ナビゲーションバーを作成していきます。ナビゲーションバーのUIを考える際には、以下のページが参考になるので、ぜひ合わせてチェックしてみてください。
ナビゲーションバー用コンポーネントを作る
NavLinkでリンクを作成します。activeClassName でクラスを指定し、該当ページにいるときだけリンクが青くなるようにしています。/
の場合にのみアクティブと判定させるために、1つ目の NavLink に exact
を指定しています。
同じクラスを何度も指定するのが少し気持ち悪い感じもします。HeaderLink
のようなコンポーネントを作って、NavLinkをラップしておくと少しスッキリするかと思います。
見た目を整える
参考までに、この記事のために作成したscssファイルも掲載しておきます。色々雑ですが、話の本筋ではないのでどうかご勘弁を・・・。
ページ用コンポーネントを作る
続いて、各リンクに対応するコンポーネントを作成しておきます。
画面遷移に成功していることだけわかればいいので、自分が何者かを表示するだけのシンプルなコンポーネントとなっています。これらはあとで、Routeコンポーネントのcomponentパラメータに指定します。
ルーティング
Routeコンポーネントで、URLとページ用コンポーネントを対応づけます。RouteにもNavLinkと同様に exact
を指定している箇所があります。exact を指定しない場合、/item1
や /item2
で Homeコンポーネントが表示されてしまうためです。
最後に、作成したコンポーネントを ReactDOM.render
でレンダリングすればページ冒頭のようなナビゲーションバーが表示されるはずです。