react-routerのv4で例えば何かの処理で分岐して遷移を行いたい場合、context.router.transitionTo()を使うことになる。
以下参考
http://stackoverflow.com/questions/39894547/navigating-programatically-in-react-router-v4
ただ、各コンポーネントがcontextに依存するのがなんとなく気持ち悪く感じたのでHOCで改善するやり方も考えてみた。
サンプルコード(contextをそのまま使う場合)
Root.js
// 省略
import { BrowserRouter, Match } from 'react-router';
// 省略
class Root extends Component {
// 省略
return (
<BrowserRouter>
<Match exactly pattern="/" component={Home} />
<Match exactly pattern="/sub" component={Sub} />
</BrowserRouter>
);
}
// 省略
Home.js
class Home extends Component {
// 省略
// contextから取得したいものを定義する。
static get contextTypes() {
return {
router: PropTypes.object.isRequired,
};
}
onClick() {
this.context.router.transitionTo('/sub');
}
return (
<div>
<button
onClick={this.onClick}
>click</button>
</div>
);
}
// 省略
サンプルコード(HOC版)
withRouter関数を定義する。
これによりpropsにrouterが追加される。
withRouter.js
import React, { Component, PropTypes } from 'react';
const withRouter = (WrappedComponent) => {
return class WithRouter extends Component {
static get contextTypes() {
return {
router: PropTypes.object.isRequired,
};
}
render() {
return <WrappedComponent {...this.props} router={this.context.router} />;
}
};
};
export default withRouter;
Home.js
// 省略
import withRouter from './path/withRouter';
// 省略
Class Home extends Component {
onClick() {
this.props.router.transitionTo('/sub');
}
return (
<div>
<button
onClick={this.onClick}
>click</button>
</div>
);
}
// withRouterの引数にHomeを渡す。
export default withRouter(Home);
HOCを複数適用したい時は(flux-utilsのContainerとか)lodashのflowRight()を使うと見やすくなる。
export default _.flowRight([
withRouter,
Container.create,
])(Home);
_.flowRightで参考にした記事
http://qiita.com/numanomanu/items/2b66d8b2887d44f857dc