- 2016/09/15 現在の情報。
- 出たばっかりなので今後変わる可能性大。
- 今まで個人的にはreact上のroutingはあんま使って来てなかったので、あんまりちゃんとした比較はできてない
- 死んだと言われたり復活したと言われたり、必要ないよ!と言われたりと不安定感すごかったので見送ってた。
- あんまり好きじゃなかったし、そこ飲んでまで使うほどの要件も無かった
-
v4のドキュメントのページ見たら可能性感じたのでとりあえず眺め回してみることにした。
- twitter上からも歓喜の声が聞こえてくる
- ドキュメントのサンプルは素晴らしいのだが、APIやQuickStartは、何故かスクロールが変な感じなので、githubを直接見るほうが良いかもしれない
- 現行のstableは2、3はalphaを出してしまったけどそこからbreaking changeしたらしくversionが4となったっぽい。
ざっくり
- 基本今までのと全部違うと言っていいぐらい違う
- めっちゃコード量減ってる
- 旧バージョンからアップデートするとなると結構書き換えは必要そうかも
installして試したかったら?
$ npm install react-router@next
package.json から見る構造変更
- v2(現行)
-
historyに依存しており、
<Router />
にはhistory
オブジェクトを渡す必要があった。 - 内部でhistoryとの結合とかを色々やってた。
-
historyに依存しており、
- v4
- history APIにがっぷりな部分はreact-historyに移植された感じ
- メンテナやOrganizationはだいたい一緒っぽい。
- ルーティング解決はpath-to-regexp
- 構成的には、You might not need React Routerで紹介されているものとかなり近い。
- history APIにがっぷりな部分はreact-historyに移植された感じ
Quick start比較
それぞれざっくり特徴が見えるところを抜粋
v2
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Link, browserHistory } from 'react-router'
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="about" component={About}/>
<Route path="users" component={Users}>
<Route path="/user/:userId" component={User}/>
</Route>
<Route path="*" component={NoMatch}/>
</Route>
</Router>
), document.getElementById('root'))
v4
quick-start (v4) からざっくり抜粋
import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter, Match, Miss, Link } from 'react-router'
const App = () => (
<BrowserRouter>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<Match exactly pattern="/" component={Home} />
<Match pattern="/about" component={About} />
<Match pattern="/topics" component={Topics} />
<Miss component={NoMatch}/>
</div>
</BrowserRouter>
)
render(<App/>, document.querySelector('#root'))
history
を渡さず、Componetとして定義出来るようになったことかなりのすっきり感がある。
<Match>
のルールも子コンポーネントで更に定義するなどもあって、親<Router />
が全体のRoutingを把握しなくても良くなっているっぽい
また、<div>
などの標準的な記法と<Match/>
の組み合わせで作られているので、HeaderやFooterやMenuなどの組み合わせがやりやすい。
ファイル数
### v2
% git clone https://github.com/ReactTraining/react-router.git
% ls -1 modules/ | grep .js | wc -l
38
### v4
% git co v4
% ls -1 modules/ | grep .js | wc -l
16
38 -> 16 と大激減!
多けりゃいい少なけりゃいいというものではないけど、内容としても見通しがよく感じる。
かなり読みやすいと感じた。
historyとのつなぎ込み部分がreact-history
に移動されたことで減った部分が多い模様。
ロゴ
ハマりどころ:<Router/>
の直下は単一のコンポーネントである必要がある
ちょっと使って見つけた部分。
MatchProvider.render(): A valid React element (or null) must be returned.
You may have returned undefined, an array or some other invalid object.
こんなエラーが出てきてなんだろうなーと思ったら<Router />
直下のComponentは一つのコンポーネントでないといけない。なので<div></div>
とかで囲まないといけない。
これは仕様らしい。
https://github.com/ReactTraining/react-router/issues/3837#issuecomment-246919642
// ダメ
const BadRoute = () => (
<Router>
<Match pattern="/" component={Foo} />
<Match pattern="/:bar" component={Baz} />
</Router>
)
// ダメ
const BadRoute = () => (
<Router>
<div>
<Match pattern="/" component={Foo} />
<Match pattern="/:bar" component={Baz} />
</div>
<div></div>
</Router>
)
// これならOK
const Route = () => (
<Router>
<div>
<Match pattern="/" component={Foo} />
<Match pattern="/:bar" component={Baz} />
</div>
</Router>
)
FAQより「なんで巨大な変更をするのか?」
2016/09/16追記項目
FAQ がREADMEに追加された。最初の項目に関して結構思想的な背景が見える部分だったので、雑訳してみる。
2016/09/16追記:FAQ がREADMEに追加された。最初の項目に関して結構思想的な背景が見える部分だったので雑訳。
- Q. なんで巨大な変更するのか?
- A. tl; dr: Declarative Composability(宣言的構築性?)のため
- 「我々はReact Routerでわくわくしたことなかった」
- 「私達が学んだことは、Reactの最も愛すべき理由が Declarative Composabillityであることです」
- 要するにReactと同じように、宣言的に記述出来るのが良いよね。という感じっぽい。
- 「staticなrouterのconfigをしないといけないせいで、下記のようなルーターは書けなかったし、Routeをラップすることもできなかった」
- 「
const CoolRoute = (props) => <Route {...props} cool={true}/>
」 - 宣言的な記述でない例として、静的なrouting configを書かないといけないことが弊害として上げられているものと思われる。
- 「
- 「routeコンポーネントのレンダリングに関与するために、
<Router createElement render>
とかcreateRouterMiddleware
快適と言えないAPIを提供していた。我々はcreateElement
を取り除き、あなたたちに返す」- うまく訳せないが、きっとAPIとしては提供しなくてもdeclarativeにすることで、「middlewareらへんはあなた達の好きな様にやってくれたらいい」という意味っぽく感じる。
- 「
onEnter
、onLeave
、onChange
のライフサイクルフックを再作成していた。けどReactには既にcomponentWillMount
、componentWillReceiveProps
、componentWillUnmunt
がある」 - 「Route configはviewヒエラルキーを記述していた。しかし、そもそもReact Componentは既にviewヒエラルキーを記述していた。」
- 「今までのReact Routerは『Reactのルーター』ではなく、『Reactのルーティングフレームワーク』だった」1
- 「Reactにとって余計なAPIだけでなく、ビルドエコシステムに対しても驚くほどやっかいな偶発的なフレームワークとなっていた」
- 「あなたはcomponentをレンダリングしてpropsを渡すことでroutingをコントロール出来る。」
-
個人的にこの表現が「おー」ってなった。 ↩