【React】redux-actionsでreducerとactionsをすっきりさせよう

# redux-actionsとは
ReactとReduxを利用する際、必ず必要となる**ActionとReducerをflux standard actionに準じた形で簡潔にかける**便利なライブラリ。

詳しくはこちら↓
[https://redux-actions.js.org/](https://redux-actions.js.org/)

redux-actionsを利用することで、Action**とReducerをすっきりさせましょう！


# 対象者
ReactとReduxを使ったことがある方

# 手順

### ComponentとContainerの準備

Componentを作成します。
`handleClickOne`と`handleClickTwo`という関数を発火させるボタンを設置しましょう。

```jsx:Component.js
import React from 'react'

const Component = (props) => {
  return (
    <div>
      <p>Hello World</p>
      <input type="button" value="One Button" onClick={props.handleClickOne} />
      <input type="button" value="Two Button" onClick={() => props.handleClickTwo('hello')} />
    </div>
  )
}

export default Component

```

Containerを作成します。
`handleClickOne`と`handleClickTwo`をActionsの`clickOne`と`clickTwo`と繋げます。

```js:Container.js
import { connect } from 'react-redux'
import Component from './Component'
import { Actions } from './Action' // Actionsは後で作成します。

const mapDispatchToProps = (dispatch) => {
  return {
    handleClickOne: () => dispatch(Actions.clickOne()),
    handleClickTwo: (text) => dispatch(Actions.clickTwo(text)),
  }

const mapStateToProps = (state) => {
  return state
}

export default connect(mapStateToProps, mapDispatchToProps)(Component)

```

### redux-actionsでreducerとactionsを作る

まずactionsからみていきましょう。
actionsには`clickOne`と`clickTwo`を定義しないといけません。

redux-actionsを使わない書き方はこちら

```js:Action.js
export const Actions = {
  clickOne () {
    return {
      type: 'CLICK_ONE',
    }
  },
  clickTwo (value) {
    return {
      type: 'CLICK_TWO',
      payload: value,
    }
  },
}

```

redux-actionsを利用した書き方はこちら

```js:Action.js
import { createActions } from 'redux-actions'

export const Actions = createActions(
  {
    CLICK_TWO: (args) => (args)
  },
  'CLICK_ONE',
)

```

どちらの書き方もおなじActionを定義しています。
**redux-actionsを利用することでかなりすっきりかける**ことがわかると思います。

引数が必要なActionは`CLICK_TWO: (args) => (args)`のように書けばよいです。
引数は`payload`に入ります。

```js
{
  type: 'CLICK_TWO',
  payload: args,
}
```

次は、reducerをみていきましょう。
reducerには`CLICK_ONE`と`CLICK_TWO`が発火したときの、ステート更新を書かないといけません。

redux-actionsを使わない書き方はこちら

```js:Reducer.js

// 初期値
const initialState = {
  text: null,
}

export const Reducer = (state=initialState, action) => {
  switch (action.type) {
    case 'CLICK_ONE':
      return {
        ...state,
      }

    case 'CLICK_TWO':
      return {
        ...state,
        text: action.payload
      }

    default:
      return state
  }
}

```

redux-actionsを利用した書き方はこちら

```js:Reducer.js
import { handleActions } from 'redux-actions'
import { Actions } from './Actions' //作成したActionsを読込

const initialState = { 
    text: null,
}

export const Reducer = handleActions({
  [Actions.clickOne]: (state, action) => ({
    ...state
  }),
  [Actions.clickTwo]: (state, action) => ({
    ...state,
    text: action.payload,
  }),
}, initialState)

```

どちらの書き方もおなじReducerを定義しています。
この程度の数だとあまり変わりないように見えますが、Actionが増えればredux-actionsを使った方がよりすっきりするのがわかります。

引数は`action.payload`で取得できます。

```js
[Actions.clickOne]: (state, action) => ({
  ...state,
  text: action.payload,
}),
```

後は通常通り、storeを作成し、Reducerを登録し、Providerタグの作ったstoreを登録すれば動きます。


#参考
[https://github.com/redux-utilities/flux-standard-action](https://github.com/redux-utilities/flux-standard-action)
[https://redux-actions.js.org/](https://redux-actions.js.org/)