connected-react-routerを使ってみた

# はじめに
初めての投稿。
これから仕事とか、暇な時にコード書いて覚えたこと、些細なことでも時間ができればメモしておこうと思います。

# connected-react-routerとは？
リポ：https://github.com/supasate/connected-react-router
A Redux binding for React Router v4（公式より）

ほうほう、ということは何ができる？

## 今のpath, hashなど、今の状態を簡単に取得できる

```jsx

import { connect } from 'react-redux'

const Child = ({ pathname, search, hash }) => (
  <div>
    Child receives
    <div>
      pathname: {pathname}
    </div>
    <div>
      search: {search}
    </div>
    <div>
      hash: {hash}
    </div>
  </div>
)

const mapStateToProps = state => ({
  pathname: state.router.location.pathname,
  search: state.router.location.search,
  hash: state.router.location.hash,
})

export default connect(mapStateToProps)(Child)

```

react-redux の connect を使ったコンポーネントは`state.router.location.pathname`という風に、今のrouterの状態を調べることができる。

## 画面遷移を簡単に

それに直接`store.dispatch`だけではなく、`react-redux`、`redux-thunk`、`redux-saga`で手軽に画面遷移をすることもできる。

#### with store.dispatch
```jsx
import { push } from 'connected-react-router'

store.dispatch(push('/path/to/somewhere'))
```

#### with react-redux
```jsx
import { push } from 'connected-react-router'

// in component render:
<div onClick={() => {

  /** do something before redirection */
  props.push('/home');

}}>login</div>

// connect the action:
export default connect(null, { push })(Component);
```

#### in redux-thunk
```jsx
import { push } from 'connected-react-router'

export const login = (username, password) => (dispatch) => {

  /* do something before redirection */

  dispatch(push('/home'))
}

```
#### in redux-saga
```jsx
import { push } from 'connected-react-router'
import { put, call } from 'redux-saga/effects'

export function* login(username, password) {

  /* do something before redirection */

  yield put(push('/home'))
}
```

他も色んなことができるが、よく使われる部分（タブン）、かつ今回で使いたい機能はこの二つですね。

# 実際に使ってみよう
以下は自分の[練習プロジェクト](https://github.com/hiroya8649/auth-practice)からのコピペ：

## historyとstore
まずは、historyとstoreの生成から。

#### history.js

```jsx
import { createBrowserHistory } from 'history';

const history = createBrowserHistory();
export default history;
```

すごく簡単ですね。

#### store.js

```jsx
import { routerMiddleware } from 'connected-react-router'; /*インポート*/
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import history from '@/common/js/history';
import createRootReducer from '@/reducer/index';

function configureStore() {
  const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
  const store = createStore(
    createRootReducer(history),
    composeEnhancers(applyMiddleware(
      routerMiddleware(history),      /*Storeに接続*/
      createLogger(),
      thunk,
    )),
  );
  return store;
}

const store = configureStore();

export default store;

```

storeを作る時に`createRootReducer(history)`と`routerMiddleware(history)`を渡せばおk。

#### createRootReducer

```jsx
export default history => combineReducers({
  router: connectRouter(history),
  auth,
  post,
});
```

## ConnectedRouterを使おう
最後は、Routerの部分をConnectedRouterにすれば完成！

```jsx
import React, { Component } from 'react';
import { ConnectedRouter } from 'connected-react-router';
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router';
import store from '@/common/js/store';
import history from '@/common/js/history';
import UserLoginPage from './container/page/UserLoginPage';

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <ConnectedRouter history={history}>
          <Switch>
            <Route exact path="/" component={UserLoginPage} />
          </Switch>
        </ConnectedRouter>
      </Provider>
    );
  }
}

export default App;

```

使用例：

#### UserAction.js

```jsx
import axios from 'axios';
import { push } from 'connected-react-router';

export function userLogin(account, password) {
  return (dispatch) => {
    axios.post('/api/sessions', { session: { email: account, password } })
      .then(({ data }) => {
        dispatch({ type: 'LOGIN_SUCCESS', payload: data });
        dispatch(push('/page/posts/view'));
      });
  };
}
```