概要
なんとなくの理解で使っているreact-router-reduxを復習しようと思い立ったところ、今やreact-router-reduxはdeprecatedになっていました。あらー。
今、React Routerのドキュメント(Redux Integrationのページ)を見ると、代わりにConnected React Routerというライブラリが紹介されています。
とはいえ、React RouterとReduxの統合は何のためか、という目的はどちらのライブラリもそう変わらないはずですので、この機会に復習していきます。
その上で、今度からはConnected ... の方を使おうと思います。
現状、こんな風に使ってた
私が書いていたコードをかいつまむと、以下の通りです(だいぶ省略してます)。
redux-thunkによる非同期アクションにおいて遷移の処理を呼びたくて、react-router-reduxを使っていました。
// React Router関連
import createHistory from 'history/createHashHistory'
import { Switch, Route } from 'react-router-dom'
// react-router-redux関連
import { ConnectedRouter, routerMiddleware } from 'react-router-redux'
// historyを作って・・・
const history = createHistory()
// Reduxのミドルウェアを設定したり・・・
const middlewares = [routerMiddleware(history), ... ]
const store = createStore(reducer, applyMiddleware([...middlewares))
// ConnectedRouterとかSwitchといったコンポーネントを並べたり・・・
const App = () => (
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
{/* Switchの下に、Routeがいくつか並ぶ・・・ */}
</Switch>
</ConnectedRouter>
</Provider>
)
// 何やら便利なpushなるものをimport
import { push } from 'react-router-redux'
export const sampleAsyncAction => async (dispatch) => {
// 非同期処理とかやったあとに・・・
dispatch(push('/samplePath')) // 次の画面へ遷移する
}
改めてReact Routerのドキュメントに立ち返る
改めて、React Router公式のRedux Integrationのページを見るのですが、どうも難しそうなことが書いてあります。
何度か読んでいるうちに、以下の理解が得られました。
- Reduxとの統合は必ずしも必要ではない。
<Link>
などで事足りるなら不要。 - アクションのディスパッチによって遷移を起こしたい時などに、統合が必要となる。例えばredux-thunkやredux-sagaによって非同期処理を行った後に、遷移したい時(今回の私のケースはこれ)。
- そうした場面では、アクションをディスパッチする際にhistoryを触れる状況を作ればよい。そうすれば、history.push(...)などのメソッドを呼んで各種遷移を起こせる。
react-router-reduxは手段の一つ
何らかの手段によって、アクションのあたりでhistoryを触れれば良い、という風にいったんまとめられそうです。
その手段の一つが、react-router-reduxのようなライブラリを導入することなのでしょう。
先ほどのコード例で登場したように、react-router-reduxにはpush
のような便利関数があります。
import { push } from 'react-router-redux'
ソースを見たところ、以下の様にして遷移が行われるようでした。
- pushを呼ぶと、アクションが作られる(アクションのtypeは、react-router-reduxの中にハードコードされている)。
- そのアクションがディスパッチされると、react-router-reduxが提供しているrouterMiddlewareがそれに反応する。
- そしてrouterMiddlewareがhistory.pushを呼ぶ。最初にApp.jsxにて、
routerMiddleware(history)
という風に呼び出しているので、routerMiddlewareはhistoryを触れるというわけ。
Connected React Routerも使用感は同じ
まだ熟読していないのですが、代替であるConnected React Routerも使い方はほぼ変わらなさそうです。
- 一番最初に、Reduxのミドルウェアなどを仕込んでおく。
- Reduxの
<Provider>
の下に、<ConnectedRouter>
を置いておく。 - pushなどをimportし、ActionCreatorにおいて利用する。
まとめ
先ほど、何らかの手段によってアクションの近辺でhistoryを触れれば良い、という風にいったんまとめました。
historyがもつpushなどのメソッドによって、遷移を起こせます。
react-router-reduxやConnected React Routerといったライブラリを使うと、好きな箇所でpushなどを呼べるようになります。例えば非同期アクションの中などで使えて便利です。
一方、やろうと思えばこれらのライブラリなしでもhistoryを触ることはできそうです。
-
<Route>
のcomponentなどには、引数としてhistoryが渡されるので(参照)、そのhistoryを親コンポーネントから子コンポーネントへと渡しまくっていき、最終的にActionCreatorの引数として渡す。 - あるいは、要所要所のコンポーネントをwithRouterで囲んでおく。withRouterで囲んでおくと、コンポーネントのpropsとしてhistoryが渡される。それを同じくActionCreatorに渡す。
とはいえこれは面倒ですので、ライブラリを使うと便利ですよ、ということなのでしょう。