connected-react-routerを使う

NO IMAGE

これまでも使ったことあったけど、設定の仕方とか忘れていたので改めてメモ。

connected-react-routerとは?

reduxのstoreでrouterを管理するためのライブラリ。それで何が嬉しいかというと、例えばsagaで以下のようにページ遷移できる。

import { push } from 'connected-react-router'
import { put } from 'redux-saga/effects'

function* login(email, password) {
  yield put(push('/home'))
}

公式のリポジトリにあるように、現状はReact Routerのv4とv5をサポートしているようです。

設定方法

store.ts

import { applyMiddleware, createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'
import createSagaMiddleware from 'redux-saga'
import { routerMiddleware } from 'connected-react-router';
import { createHashHistory } from 'history';
import reduxLogger from 'redux-logger'
import rootSaga from './sagas'
import reducers from './reducer'

export const history = createHashHistory()
const sagaMiddleware = createSagaMiddleware()

const configureStore = () => {
  const store = createStore(
    reducers(history),
    composeWithDevTools(
      applyMiddleware(
        routerMiddleware(history),
        sagaMiddleware,
        reduxLogger
      )
    )
  )

  sagaMiddleware.run(rootSaga)
  return store
}

export default configureStore

reducers(history)とrouterMiddleware(history)が該当箇所。sagaやロガーの設定も混ざっています。

reducer.ts

import { combineReducers } from 'redux'
import { connectRouter } from 'connected-react-router'
import login from './modules/login/reducer'


export default (history: any) => combineReducers({
  login,
  router: connectRouter(history)
})

取り急ぎ、any使っちゃっています。

index.tsx

import * as React from 'react';
import { render } from 'react-dom';
import { Route, Switch } from 'react-router-dom';
import { ConnectedRouter as Router } from 'connected-react-router';
import { Provider } from 'react-redux'
import configureStore, { history } from './store'
import Login from './components/login'

const App: React.SFC = () => (
  <Provider store={configureStore()}>
    <Router history={history}>
      <Switch>
        <Route exact path="/" component={Login} />
      </Switch>
    </Router>
  </Provider>
);
render(<App />, document.getElementById('root'));