Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

最初に

実はもともと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使っちゃいるけど使いこなせていない・・・。もっと使いようがあると思うので、今後勉強していこうと思う。

102Design
株式会社ブラキオ 代表取締役 JavaScript, TypeScript, Reactを中心にコード書いてます。 2児の父。フットサル、麻雀が趣味
https://brachio.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away