react-routerとreact-router-domの違い

Created: May 22, 2020 3:02 PM
Last Edited: August 14, 2021 3:09 PM

reactのRoutingライブラリはreact-routerとreact-router-domがあります。

「react-routerがv4から改称してreact-router-domになったんだ!」みたいな印象がありますが(me too)。厳密にいうと違います。

react-router でググって一番上にくる記事がいきなりnpm install --save react-router-dom とかしてるのでややこしいのですが。

💡
この記事はUbiregi Advent Calendar 2019 2日目のために書かれたものでしたが、Qiitaからこちらに転載しました。

なにはともあれ

READMEを見てみましょう。今はv5です。

react-router-domはDOMバインディングなreact-routerだよ〜って書いてあります。

loading
react-router Declarative routing for React.
loading
react-router-dom DOM bindings for React Router.

ちなみにreact-router-nativeってのもあります。

使い方を比較

Home,About,Dashboardはあらかじめ用意したコンポーネントです。

react-router

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Switch } from 'react-router';
import { createBrowserHistory } from 'history';
import { Home, About, Dashboard } from './component';

const App = () => {
    return (
        <Router history={createBrowserHistory()}>
            <div>{document.title}</div>
            <Switch>
                <Route exact path='/'><Home /></Route>
                <Route path='/about'><About /></Route>
                <Route path='/dashboard'><Dashboard /></Route>
            </Switch>
            <a href='/'>Back To Home</a>
        </Router>
    )
}

react-router-dom

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';
import { Home, About, Dashboard } from './component';

const App = () => {
    return (
        <BrowserRouter>
            <div>{document.title}</div>
            <Switch>
                <Route exact path='/'><Home /></Route>
                <Route path='/about'><About /></Route>
                <Route path='/dashboard'><Dashboard /></Route>
            </Switch>
            <Link to='/'>Back To Home</Link>
        </BrowserRouter>
    )
}

パッと見、違いとしては以下の感じです。 1. react-routerは<Router />historyを渡している 2. react-routerはaタグだが、react-router-domは <Link/> を使用している。

2に関してはのAPIをみた方が早い。 1について調べていきます。

RouterとBrowserRouterの違い

結論から書きますと、この二つにあまり違いはありませんでした。

実装を見てみます。

loading

見た通りですが、BrowserRouterは内部でRouterを使用しており、historyをpropsに渡しています。単なるWrapperですね。

class BrowserRouter extends React.Component {
  history = createHistory(this.props);

  render() {
    return <Router history={this.history} children={this.props.children} />;
  }
}

PropsTypesではいくつかoptionalなパラメータが定義されていますが、これらのpropsは全てhistoryへ渡されるので、RouterでもcreateBrowserHistoryにパラメータを渡すことで同じようなことが実現できます。

BrowserRouter.propTypes = {
  basename: PropTypes.string,
  children: PropTypes.node,
  forceRefresh: PropTypes.bool,
  getUserConfirmation: PropTypes.func,
  keyLength: PropTypes.number
};

以下はbasenameとforceRefreshを指定した例

const App = () => {
    return (
        <Router history={createBrowserHistory({ basename: '/', forceRefresh: true })}>
            <div>{document.title}</div>
            <Switch>
                <Route exact path='/'><Home /></Route>
                <Route path='/about'><About /></Route>
                <Route path='/dashboard'><Dashboard /></Route>
            </Switch>
            <a href='/'>Back To Home</a>
        </Router>
    )
}

あんまり違わないけど…

react-routerもreact-router-domも「Routingをする」だけならば同じように使えます。useHistory, userLocation, useParams, useRouteMatch といったhooksもreact-routerに実装があります。

ただ、当然のことをいうと、react-routerだけを使用してもあまり嬉しくありません、<Link /><NavLink />といったAPIが使用できませんしね。

<Router />の活用…?

最後に<Router />の活用を考えてみましょう。前述したようにBrowserRouterはRouterのWrapperなので、<Link /><NavLink />といったAPIも同じように使えます。 historyを別でinstallしなければなりませんが、まぁいいでしょう。

RouterとBrowserRouterの違いはただ一つ、historyを外部から渡すことができる。 これだけです。 なので、ReactGAと組み合わせてトラッキングが…とか思いましたが、調べたらすでにやってる方がいらっしゃいました。更に言えばuseEffect使う形に落ち着いてた。

https://github.com/react-ga/react-ga/issues/122

更に更に言えばuseLocationを使った例が公式にありました。

loading

結論

迷わずreact-router-domを使おう。

蛇足

ぼんやりとreact-routerのissueを眺めてたらこんなdiscussionがされていました。

loading

react-routerに依存している別のパッケージがあった時に、バージョンが不一致だと競合するからreact-router-domをreact-router配下のパッケージにしようよーみたいな感じですね。 react-router-nativeに全くメリットがないのと、そもそもreact-routerは直接依存するものではない?ようなので、積極的ではないのかなと思いますが。


<-

<<-