immutable-js
React
redux

Immutable.jsを使ってReduxのReducerとComponent周りがスッキリした

最初に

実はもともとImmutable.jsは使っていて特にRecordsを使ってReduccerとStateの管理を分離していたんだけど、同じようにComponentもスッキリさせることができることを知ったのでまとめてみる。

Reducer & Action周り

Reduxでアプリケーションを作っていると、どうしてもReducer周りかComponentがごにょごにょせざるをえなくなりかなり見辛いコードになってしまう。

Reducerは交通整理だけに専念するためにImmutable.jsを使う。このImmutable.jsはいろんなことできるようだけど、自分はRecords以外あまりうまく使えていない汗

自分がよくやるのはRecordsにStateを持たせるやり方。よくあるModel的な役割をさせる。

import Users from '../records/Users'

// ActionTypes
export const SUCCESS_USERS_GET = 'SUCCESS_USERS_GET'

// Action
export successUsers = (data) => {
return {
    type: SUCCESS_USERS_GET
    payload: data
  }
}

// Reducer
export const usersReducer = (state = new Users, action) => {
  const {type} = action
  switch (type) {
    case SUCCESS_USERS_GET:
      return state.succeeded(action.payload)
    default:
      return state
  }
}

Records

Recordsでは色々操作できるようにメソッドを作る感じ。succeededでは取得したresponseをlistにsetしている。基本的な使い方としてはこれだけで済むんだけど、
Componentでごにょごにょするケースに対応できない。例えばlistの逆順が欲しいとか、userのidだけの配列が欲しいとか。これをcomponent側でやり始めるとコードが混沌としてくる。

そこでgetReverseListみたいなメソッドを作っておくことで、componentではlistが逆順になったものをただ受け取って表示させるっていう仕事だけにすることができる。

import { Record } from 'immutable'

const UsersRecord = Record({
  list: []
})

export default class Users extends UsersRecord {
  succeeded(action) {
    return this.set('list', action.response)
  }

  getReverseList() {
    return this.list.slice().reverse()
  }
}

component

componentで使う場合はmapDispatchToPropsで呼び出すことができる。これで何も考えずにComponentでは逆順になったlistを使うことができる。

import { bindActionCreators } from 'redux'
import React, { Component } from 'react'
import { connect } from 'react-redux'

class MyComponent extends Component {
  constructor(props) {
    super(props)
  }

  getUsers() {
    // ここでAPIを叩く
  }

  render() {
    const {list} = this.props
    return (
      <Component list={list}/>
    )
  }
}

function mapStateToProps(state, ownProps) {
  return {
    list: state.user.getReverseList()
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    Object.assign({},{successUsers}),dispatch
  )
}

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(MyComponent)
)

色々解決

Immutable.jsを使うことでこうゆうのとか

render() {
  const {list} = this.props
  const reverseList = list.slice().reverse()
  return <PageComponent list={reverseList} />
}

こうゆうのとかをやらなくてよくなった。

createReverseList() {
    const {list} = this.props
    return list.slice().reverse()
  }

  render() {
    return <PageComponent list={this.createReverseList()} />
  }

これを知ってからというものImmutable.jsが手放せなくなり、同時にComponent内がスッキリさせることができた。もっと早くに知っておけばと思う今日この頃。

反省点

Immutable.js使っちゃいるけど使いこなせていない・・・。もっと使いようがあると思うので、今後勉強していこうと思う。