React Router v4(next) が alphaからbetaになってぼちぼち変わってたので追従する

  • 53
    いいね
  • 1
    コメント

ということでreact-router@v4がalphaからbetaになった。
かなりアグレッシブに変更されていて色々変える所あったのでメモ 1 2

packageの分離

react-routerは下記の3パッケージに分離した

  • react-router

  • react-router-dom

    • ブラウザ用
    • 今までのreact-rouerの機能がこっちにごそっと移動された感じ
    • 現行、react-routerの機能をre-importして提供されているものもあるが、stable時にどうなるかは不明。
    • このパッケージに含まれるもの
      • <BrowserRouter>
      • <HashRouter>
      • <Link>
      • <NavLink> (2017/02/01時点ではまだUndocumented, まだ不安定気味。後述)
      • react-routerを一通り再importしたもの
  • react-router-native

    • ネイティブ用
    • あんまり自分の要件で使うことがなさそうなのでスルー気味。
    • Android用とiOS用が分岐してるっぽく見える。
    • <NativeRouter>というのがRouterになるもよう

documentationの変更

URLが新しくなった。

https://reacttraining.com/react-router/

alpha版のドキュメントリダイレクトされてしまうため、github漁るぐらいでしか出てこなそう

installationsの変更

パッケージが分離したので、react-routerではなくreact-router-domをinstallするようになる。

"react-router": "4.0.0-alpha.6",

"react-router-dom": "4.0.0-beta.3",

Installationには「react-router-dom@nextでインストールしてね!」というのがあるが、この方法でインストールするとバージョンがダイナミックに変わるので、個人的にはバージョンベタ決めでいいんじゃないかと思っている。
(以前からreact-router@nextでinstallしてたら今回の変更で無事死亡していただろう)3

コードベースの変更

<Match>は廃止。<Route>になった(戻った)

// 旧(alpah)
<Match pattern="/user/:id" />

// 新(beta)
<Route path="/user/:id" />

このコミットで変わった。
明確な理由は見つけられなかったが、現行バージョンに近い形に戻された。

v2/v3からの移植も楽になるっぽい

<Miss>が廃止。<Switch>で代用

下記のサンプルがわかりやすい。
https://reacttraining.com/react-router/examples/no-match

// 旧(alpha)
<div>
  <Match pattern="/foo" component={ Foo } />
  <Miss component={ NotFound } />
</div>

// 新(beta)
<Switch>
  <Route path="/foo" component={ Foo } />
  <Route component={ NotFound } />
</Switch>

<Switch>は、若干理解しづらいが、「Routeが 包括的(inclusively) にレンダリングするのに対し、Switchは 排他的(exclusively) にレンダリングするという機能らしい。

このコンポーネントが出来た事で、「どれにも当てはまらなかった場合」という場合にpathが無いrouteを出して排他的に処理することでNotFoundな場合のコンポーネントとして扱える。このためMissは不要になった、ということらしい。

<Link>からactive系のが消えた。<NavLink>になる予定

これまで<Link>は現在のURLと同じURLの場合にactiveClassNameのstyleがあたる、というようなものを持っていたりしたが、新しい<Link>はこのあたりのstyle管理を持たなくなった。
代替として<NavLink>というコンポーネントがこの代替をする予定のようだが、今のところundocumentedで若干不安定。

今のところで言うと<Route>を作ってサクッと自前でやることも可能。
こちらのサンプルに乗っている
https://reacttraining.com/react-router/examples/custom-link

// 旧(alpha)
<Link to="/about" activeClassName="active">
  About
</Link>

// 新(beta)(代替バージョン)
const SomeLink = ({ label, to, activeOnlyWhenExact }) => (
  <Route path={to} exact={activeOnlyWhenExact} children={({ match }) => (
    // children要素でfuncを渡すことで、この<Route>がmatchしたかどうかなど判定出来る。
    <div className={match ? 'active' : ''}>
      {match ? '> ' : ''}<Link to={to}>{label}</Link>
    </div>
  )}/>
)

<Match(Route)>のproperty変更: exactly -> exact

Match(現Route)のexactlyというproertyがexactになった。

// 旧(alpha)
<Match exactly ... />

// 旧(bet)
<Route exact ... />

https://github.com/ReactTraining/react-router/issues/4237

exactlyってよりexactの方が正しいのでは?ってことっぽい(あんまりここらへんのニュアンスわかってない)

<NavigationPrompt> -> <Prompt>

個人的にはまだ使ってなかった機能だったのでハマってなかったが、ドキュメント眺めてたら変更されているようだった。おそらくreact-router-nativeを見越しての命名変更だろう。
ドキュメント見比べても中身はそんなに変わってなさそう

新機能など

<Route strict>が追加された

https://reacttraining.com/react-router/#route.strict

個人的にすごい嬉しい機能。
今まで最後の/(スラッシュ)が無視されなかったが、デフォルトでは無視されるようになった。
Matchと同様スラッシュを区別したい場合にこのプロパティを渡すと良い

  • <Route path="/foo/bar"> -> /foo/bar/でマッチ
  • <Route path="/foo/bar" strict> -> /foo/bar/でマッチしない(旧Matchの仕様と同じ)

withRouterが追加された

いわゆるRouterのHigherOrderComponent.
何か複雑なことをやる場合に必要になりそうだが、基本そんなに使わなそう


  1. 「unstableだし覚悟はしてたけど、やってくれたな!」という気持ちありつつ、「乗り換えたいライブラリもないし、自前しても同じような感じになりそうだし、幸いv4-alphaのコードはある程度把握してるし、まあ気軽に心中してみるか」という気持ちで臨んだ。 

  2. 自分が見つけられた部分だけです。他にもあったらコメント欄 or 編集リクエストでもいただければ幸いです。 

  3. 本音を言えばreact-router@betaとかreact-router@v5.0.0-betaとかでpublishしてほしかった気持ちが無くもない