HTML5テクニカルノート
Create React App + React Router入門 01: ルーティングを定める
- ID: FN2005001
- Technique: ECMAScript 2015
- Library: React 16.13.1 / React Router 5.1.2
シングルページアプリケーション(SPA)は、ひとつのページでコンテンツを切り替えます。画面が素速く遷移でき、ユーザー体験を高めるための仕組みです。けれどURLが変わらないと、遷移した画面の中のひとつを見ることがむずかしくなります。画面に表示するコンポーネントとURLを結びつけるのが、ルーティングモジュールであるReact Routerの役割です。
01 ルートを定める
Create React AppでつくったReactアプリケーションのひな型に、手を加えてゆきます(ひな型アプリケーションのつくり方については、「Create React App 入門 01: 3×3のマス目をつくる」01「Reactアプリケーションのひな形をつくる」をお読みください)。そのうえで、react-router-dom
をインストールしてください(「Quick Start」参照)。
npm install react-router-dom
react-router-dom
に備わるルーターはふたつで、<BrowserRouter>
と<HashRouter>
です。URLのもち方と、Webサーバー側の設定に違いがあります。
<BrowserRouter>
が用いるパスは、通常のURLです。ただし、サーバーがそのために正しく設定されていなければなりません。それに対して、<HashRouter>
はURLに添えるハッシュでルーティングされます(http://example.com/#/your/page
)。サーバー側の設定は要りません。今回使うのは、<BrowserRouter>
です。
ルーター(<BrowserRouter>
)の中に<Route>
コンポーネントでpath
を定め、ルーティングするコンポーネントはその子として差し込みます。モジュールsrc/App.js
は、つぎのように書き替えてください。URLを指定したパスに書き替えれば、コンポーネントがルーティングされるでしょう(図001)。
src/App.jsimport React from 'react'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import './App.css'; function App() { return ( <Router> <Route path="/home"> <Home /> </Route> <Route path="/products"> <Products /> </Route> <Route path="/settings"> <Settings /> </Route> </Router> ); } const Home = () => ( <h2>Home</h2> ); const Products = () => ( <h2>Products</h2> ); const Settings = () => ( <h2>Settings</h2> ); export default App;
図001■指定したパスによってコンポーネントがルーティングされる
02 リンクで遷移する
パスを手入力するのでなく、リンクで遷移させましょう。このとき用いるのは、<a>
要素ではなく<Link>
コンポーネントです。リンク先パスはto
で定めてください。モジュールsrc/App.js
には、つぎのように書き加えます。これでリンクをクリックすれば、コンポーネントが切り替わります。モジュールsrc/App.css
により、以下のコード001のような簡単なスタイルを割り当てました。
src/App.jsimport { Link } from 'react-router-dom'; function App() { return ( <Router> <nav> <ul> <li> <Link to="/home">Home</Link> </li> <li> <Link to="/products">Products</Link> </li> <li> <Link to="/settings">Settings</Link> </li> </ul> </nav> </Router> ); }
図002■リンクでコンポーネントが切り替わる
コード001■アプリケーションのスタイル
src/App.css
body {
padding-left: 0.5rem;
}
nav ul {
display: flex;
padding: 0;
}
nav ul li {
display: inline;
margin-right: 0.5rem;
}
03 パスの検索と一致
ホームのページは、ルート(/
)に定めるのが普通でしょう。そこで<Link>
のパスをつぎのように書き替えます。すると、他のリンクを選んでも、ルートのコンポーネント(Home
)もつねに表示されてしまうのです(図002)。これは、ルーティング先の決め方に原因があります。<Route>
のpath
は、与えられたURLと頭の部分が一致していればよく、しかもひとつとは決まっていないのです。たとえば、URLを"/products/something"
としてもProducts
コンポーネントは表示されます。つまり、ルート(/
)のコンポーネントは、必ず表示されるということです。
src/App.jsfunction App() { return ( <Router> <nav> <ul> <li> {/* <Link to="/home">Home</Link> */} <Link to="/">Home</Link> </li> </ul> </nav> {/* <Route path="/home"> */} <Route path="/"> <Home /> </Route> </Router> ); }
図003■pathの指定部分が一致したRouteはすべて表示される
ひとつの対応の仕方は、<Route>
に、つぎのようにexact
を加えることです。これで、厳密にルートパス(/
)でないかぎりHome
コンポーネントは表示されません。その代わり、存在しないたとえば/home
はルーティング先がないことになります。
src/App.jsfunction App() { return ( <Router> {/* <Route path="/"> */} <Route exact path="/"> <Home /> </Route> </Router> ); }
04 パスが一致した最初のルートを選ぶ
<Switch>
の中に<Route>
コンポーネントを定めれば、path
の一致した最初のコンポーネントだけがルーティングされます。複数表示されることはありません。この場合、ルートパス(/
)を最後の<Route>
のpath
に置けば、デフォルトのルートになるということです。つぎのコードでは、"/home"
などまったく存在しないURLに対してもルート(Home
)のコンポーネントが表示されます(図004)。
src/App.jsimport { Switch, } from 'react-router-dom'; function App() { return ( <Router> <Switch> {/* <Route exact path="/"> <Home /> </Route> */} <Route path="/"> <Home /> </Route> </Switch> </Router> ); }
図004■存在しないURLにはルートパスのコンポーネントが表示される
書き上げたアプリケーションモジュールsrc/components/Square.js
の記述全体は、つぎのコード002のとおりです。併せて、CodeSandboxに以下のサンプル001を公開しました。
コード002■アプリケーションのモジュール
src/App.js
import React from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from 'react-router-dom';
import './App.css';
function App() {
return (
<Router>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/products">Products</Link>
</li>
<li>
<Link to="/settings">Settings</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/products">
<Products />
</Route>
<Route path="/settings">
<Settings />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
);
}
const Home = () => (
<h2>Home</h2>
);
const Products = () => (
<h2>Products</h2>
);
const Settings = () => (
<h2>Settings</h2>
);
export default App;
サンプル001■React Router 01: Basic Routing
05 ルーティングパスを厳密に一致させる
厳密に一致したパスにルーティングさせたい場合について、簡単に解説を加えておきます。<Route>
すべてにexact
を添えれば済むのはたしかです。けれどそのままでは、一致しない場合にページが空白となってしまいます。それを避けるには、最後の<Route>
にエラー(404)ページを置くとよいでしょう。そのときは、つぎのようにpath
は与えません。確認のため、以下のサンプル002をCodeSandboxに公開しました。
src/App.jsfunction App() { return ( <Router> <Switch> <Route exact path="/products"> <Products /> </Route> <Route exact path="/settings"> <Settings /> </Route> <Route exact path="/"> <Home /> </Route> <Route> <NoMatch /> </Route> </Switch> </Router> ); } const NoMatch = () => ( <h2>Not Found</h2> );
サンプル002■React Router 02: Basic Routing to Exact Paths
Create React App + React Router入門
- Create React App + React Router入門 01: ルーティングを定める
- Create React App + React Router入門 02: ページの遷移と状態の保持
- Create React App + React Router入門 03: ルーティングを入れ子にする
- Create React App + React Router入門 04: フックuseRouteMatch()とuseHistory()を使う
作成者: 野中文雄
作成日: 2020年05月08日
Copyright © 2001-2020 Fumio Nonaka. All rights reserved.