LoginSignup
11
6

More than 3 years have passed since last update.

爆速Redux ES6だけで現代風コードダイエット

Last updated at Posted at 2018-12-03

alt

redux素晴らしい

パフォーマンス良し、テスト良し、デバッグ良し、エコシステム良し。
私はreact nativeの人なのですが、redux-persistを使いたいために、2019年でもreduxを使い続けると思います。

ただreduxにも弱点があります。学習コストの高さと、記述量の多さです。
そのため、reduxの記述量を減らすためのライブラリが数多く生み出されてきました。
redux-actions, redux-sauce, etc...

時代はES6へ変わりました、現代風のreduxの書き方で記述量を半分にダイエットしましょう。

完成品は以下のurlにあります。
https://github.com/soniczsonic/reduxtuto/tree/master

一般的なreduxの書き方

userの名前を扱うreduxです。

// redux.js
export const deleteName = () => ({  
  type: 'DELETE_NAME',
  name: ''
});

export const setName = name => ({  
  type: 'ADD_NAME',
  name: name,
});

INITIAL_STATE = {
  name: 'Nanasi'
}

export default (state = INITIAL_STATE, action) => {  
  switch (action.type) {
    case 'ADD_NAME':
      return {...state, name: action.name}
    case 'DELETE_NAME':
      return {...state, name: ''}
    default:
      return state;
  }
}

よくあるswitch文です。記述量が多いですね。
ここで目をつけるのが一箇所。

そもそもAcrion creator いらないのでは

そう、今回はactionを直接viewに書き込みます。意外にも、スッキリしたコードになります。
(ただし、この書き方はredux-thunkとは併用できません。redux-sagaか、redux-observableなどを使いましょう)

まずjsのオブジェクトについておさらい

  1. オブジェクトリテラル。 オブジェクトリテラルとは{}で囲むとオブジェクトを作ることができる構文です。new classとだいたい同じです。 つまり、
obj = {name: 'kabaya' sayName: () => console.log('kabaya desu.')}
と書けます
obj.nameとobj.sayNameを実行してみましょう

2.hasOwnProperty
objectが特定のkeyを持っているかを真偽値で返します。

obj.hasOwnProperty('name') // true
obj.hasOwnProperty('sex') // false

以上のことを後で使うので覚えておいてください。

reduxをダイエット。

まず用意するのは以下のcreateReducer関数です。純粋なjsで作ったスニペットです。
jsのカリー化を使ってfunction fucoryと呼ばれるものを作ります。
つまり、functinonを作成するためのfunctionを作ります。

// createReducer.js
export function createReducer(initialState, actionHandlers) {
  return function reducer(state = initialState, action) {
    if (actionHandlers.hasOwnProperty(action.type)) {
      return actionHandlers[action.type](state, action)
    } else {
      return state
    }
  }
}

上のcreateReducer関数を使うと、reduxが以下のように書けます。

// superUserRedux.js
import createReducer from './createReducer'

INITIAL_STATE = {
  name: 'Super User',
  age: 16
}

const actions = {
  SET_SUPER_USER_NAME: (state, action) => ({...state, name: action.name, age: action.age}),
  DELETE_SUPER_USER: (state, action) => ({...state, name: '', age: 0})
}

export default createReducer(INITIAL_STATE, actions)

type: 'ACTION'と直接書き込みます。

// heme.js
const mapDispatchToProps = dispatch => ({
  // actionCreatorをimportした場合
  setName: (name) => dispatch(setName(name)),
  deleteName: () => dispatch(deleteName()),
 // actionCreatorをimportしない場合。
  setSuperUser: (name, age) => dispatch({type: 'SET_SUPER_USER_NAME', name, age}),
  deleteSuperUser: () => dispatch({type: 'DELETE_SUPER_USER'}),
})

注意

dispatchの中のactionのプロパティと、reducerの引数の名前は一致している必要があります。
つまり、

setSuperUser: (name1, age) => dispatch({type: 'SET_SUPER_USER_NAME', name1, age})

とした場合は、
reducerの方でも

SET_SUPER_USER_NAME: (state, action) => ({...state, name: action.name1, age: action.age})

とnameをname1に変えてあげる必要があります。
なぜかというと、dispatch()の引数は、reducerにactionという形で渡されるからです。
つまり、
SET_SUPER_USER_NAME: (state, action)のactionの中身は{type: 'SET_SUPER_USER_NAME', name, age}ということです。

さらに簡潔に

mapDispatchToProopsのショートハンドを使いましょう。
実は、dispatchを使わずに、action creatorを直接、mapDispatchToPropsに書き込めます。

// heme.js
const mapDispatchToProps = {
  // actionCreatorをimportした場合
  setName,
  deleteName,
 // actionCreatorをimportしない場合。
  setSuperUser: (name, age) => ({type: 'SET_SUPER_USER_NAME', name, age}),
  deleteSuperUser: () => ({type: 'DELETE_SUPER_USER'}),
}

ES6の力は偉大ですね。
純粋なjsだけでこれほどreduxの記述量を減らすことができました。

参考url
https://medium.freecodecamp.org/reducing-the-reducer-boilerplate-with-createreducer-86c46a47f3e2

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6