2016年9月27日火曜日

Immutable.jsを使ってReactで入れ子になってるstate更新をするとかそういったときに楽しよう的なお話

  • このエントリーをはてなブックマークに追加

Reactを使っていると頻繁に発生するstateの更新。
もちろん単純にthis.setState(obj)とかやってあげればいいわけだけど、
objが入れ子になっている中での深い階層の一部を変更したいとかそういう場合はかなり面倒。

ということで今日はImmutable.jsを使えばこれはかなり楽になるよというお話をば。

■Immutable.jsを使った例

$ npm install --save-dev immutable
import React from "react"
import Immutable from 'immutable';

export default class Home extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      checkbox:{
        check1:false,
        check2:true
      }
    }

    this.changeCheck1 = this.changeCheck1.bind(this)
    this.changeCheck2 = this.changeCheck2.bind(this);
  }

  // immutable.jsを使わない例
  changeCheck1(e){
    var newState = Object.assign({},this.state);
    newState.checkbox.check1 = e.currentTarget.checked;

    this.setState(newState);
  }

  // immutable.jsを使った例
  changeCheck2(e){
    var newState = Immutable.fromJS(this.state)
    .updateIn(['checkbox','check1'],v => e.currentTarget.checked)
    .toJS();

    this.setState(newState);
  }

  render(){
    return (
      <input type="checkbox" name="check1" value="1" onChange={this.changeCheck1} />
      <p>{this.state.checkbox.check1?'check1 is checked':'check1 is not checked'}</p>
      <input type="checkbox" name="check2" value="1" onChange={this.changeCheck2} />
      <p>{this.state.checkbox.check2?'check2 is checked':'check2 is not checked'}</p>
    )
  }
}

単純にこの例だとimmutable.js使っても使わないでも一緒だよねとは思ったりなんだり。
ただonChange={(e) => {}}という感じで、この中で一行でやるとかであるとなるとimmutable.jsの方が楽かなと。
中身を複雑に処理をしようとすればするほどimmutable.jsの方が楽なんじゃないかなと。
多分これぐらいだったら全然使う必要はないんだけど。

ちなみにthis.setState({check1:false,check2:true})という形で入れ子になっていない場合は、
this.setState({check1:true})とやってもcheck2:trueはそのまま残っているが、
入れ子の中身を指定してsetStateしようとすると他の値が破壊されてしまうので注意。
this.setState({checkbox:{check1:true}})はcheck2:trueが消えてしまうので注意

※気をつけよう的なこと
・.toJS()をしないとImmutable.jsでのオブジェクトになっていて、stateとして扱えない
・.toJS()はImmutable.fromJS()として引っ張ってきたものにしか使えない
・Immutable.Map()したものは.toObject()とかでオブジェクトに戻すことができる

ってな感じでImmutableを使ってみよう的な。
自分が書いた例があまりよくないからメリットを感じることはできないんだけど、
大規模だったり複雑な感じになればなるほどImmutable.jsが活躍する機会は増えるわけで。
ただ自分が使いたいオブジェクトに戻す際に、MapでやったのかfromJSでやったのかで変わるから注意しよう的なみたいな

Adsense