react-routerを使ったSPA

やりたいこと

  • React でSPA
  • react-routerを使う

github.com

基本的にreact-router-domのチュートリアルに従えば簡単に実装可能。

reacttraining.com

あとpath/*を指定することで、想定されていないpathが入力されたとき、404ページを表示している。

npm install

npm install react-router-dom

react-router-dom実装

実装前

// App.js
import React from 'react';
import Helmet from 'react-helmet';
import AppBurnDownView from './AppBurnDownView';
import '../css/App.css';

const App = () => (
  <div className="App">
    <Helmet>
      <meta charSet="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
      <title>BurnDown App</title>
    </Helmet>
    <AppBurnDownView />
  </div>
);


export default App;

実装後

// App.js
import React from 'react';
import {
  BrowserRouter as Router, Switch, Route, Link, Redirect,
} from 'react-router-dom';
import Helmet from 'react-helmet';
import AppBurnDownView from './AppBurnDownView';
import AppVelocityView from './AppVelocityView';
import '../css/App.css';

const App = () => (
  <div className="App">
    <Helmet>
      <meta charSet="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
      <title>BurnDown App</title>
    </Helmet>
    <Router>
      <header>
        <Link to="/burndown">BurnDown</Link>
        <Link to="/velocity">Velocity</Link>
      </header>
      <Switch>
        <Route exact path="/">
          <Redirect to="/burndown" />
        </Route>
        <Route path="/burndown">
          <AppBurnDownView />
        </Route>
        <Route path="/velocity">
          <AppVelocityView />
        </Route>
        <Route path="/*">
          <p>404</p>
        </Route>
      </Switch>
    </Router>
  </div>
);


export default App;

ハマりかけたこと

下記のようにルートパス(/)の表示コンテンツをAppBurnDownViewにしたとき、
他のLinkを選択しても画面遷移が行われなかった。
そのため、ルートパス(/)のときはredirectで他のコンテンツを表示するパスに飛ばすようにした。

// 正しく画面遷移しない
const App = () => (
  <div className="App">
    <Helmet>
      <meta charSet="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
      <title>BurnDown App</title>
    </Helmet>
    <Router>
      <header>
        <Link to="/">BurnDown</Link>
        <Link to="/velocity">Velocity</Link>
      </header>
      <Switch>
        <Route path="/">
          <AppBurnDownView />
        </Route>
        <Route path="/velocity">
          <AppVelocityView />
        </Route>
      </Switch>
    </Router>
  </div>
);

公式のチュートリアルではRedirectを使わないで、
画面遷移させるリンクに<Link to="/">Home</Link>を指定いる。
また、Routeタグ内も、path/の時に<Home />コンポーネントを表示させているため、
上記のコードで正しく画面遷移されない理由がよくわからない。

が、とりあえず目的は達成できているので、深く考えないことにした。