React Routerにおけるルーティング定義ファイル分割方法

React Routerとは

React RouterはReactによって作るSPAで使うルーティング管理ライバーリーです。 https://reacttraining.com/react-router/

分割前

公式ドキュメントのサンプルでルーティングの定義はこんな感じです。 分割の仕方について紹介されていません。

<Router>
  <Switch>
    <Route path="/" exact component={Home} />
    <Route path="/will-match" component={WillMatch} />
    <Route component={NoMatch} />
  </Switch>
</Router>

分割方法①

ファイル#1

export default const Routes = () => (
  <Switch>
    <Route path="/" exact component={Home} />
    <Route path="/lovely" exact component={Lovely} />
  </Switch>
);

ファイル#2

export default const AnotherRoutes = () => (
  <Switch>
    <Route path="/cute" exact component={Cute} />
    <Route path="/clean" exact component={Clean} />
  </Switch>
);

分割統合ファイル

import Routes from "./Routes";
import AnoterRoutes from "./AnotherRoutes";

export default const App = () => (
  <Router>
    <Routes />
    <AnotherRoutes />
  </Router>
);

この方法で一般的なルーティング定義は大丈夫ですが、複数のSwitchコンポーネントの影響で、404ページの指定ができません。 下記のように公式ドキュメントみたいな感じに404ページを指定すると、404部分のコンポーネントはずっと出ていることとなります。

import Routes from "./Routes";
import AnoterRoutes from "./AnotherRoutes";

export default App = () => (
  <Router>
    <Routes />
    <AnotherRoutes />
    <Route component={NoMatch} />
  </Router>
);

分割方法②

ファイル#1

export const routes = [
  <Route path="/" key="/" exact component={Home} />,
  <Route path="/lovely" key="/lovely" exact component={Lovely} />
];

ファイル#2

export const anotherRoutes = [
  <Route path="/cute" key="/cute" exact component={Cute} />,
  <Route path="/clean" key="/clean" exact component={Clean} />
];

分割統合ファイル

import { routes } from "./Routes";
import { anotherRoutes } from "./AnotherRoutes";

export App = () => (
  <Router>
    <Switch>
      {routes}
      {anotherRoutes}
      <Route component={NoMatch} />
    </Switch>
  </Router>
);

この方法によって、全部のRouteコンポーネントは一つのSwitchコンポーネントの下になります。 404ページの定義は可能となります。

React 16から

React 16ではFragmentという素晴らしい特性を入れました。 https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html これによりもっと綺麗にかけます。

ファイル#1

export default const Routes = () => (
  <React.Fragment>
    <Route path="/" exact component={Home} />
    <Route path="/lovely" exact component={Lovely} />
  </React.Fragment>
);

ファイル#2

export default const AnotherRoutes = () => (
  <React.Fragment>
    <Route path="/cute" exact component={Cute} />
    <Route path="/clean" exact component={Clean} />
  </React.Fragment>
);

分割統合ファイル

import Routes from "./Routes";
import AnoterRoutes from "./AnotherRoutes";

export default const App = () => (
  <Router>
    <Routes />
    <AnotherRoutes />
    <Route component={NoMatch} />
  </Router>
);

まとめ

大型SPAを構築するとき、ページ数が多くてルーティング定義を分割するのが必要だと思います。 Switchの定義じゃなくて、Routeコンポーネント配列を複数ファイルに分けた方が良いかと思います。 React 16のFragment特性によりもっと綺麗に分けることができます。