WantedlyでReactとImmutable.jsをどう使っているか
Immutable.jsとReact@Wantedly入門編Kento Moriwaki / 森脇健斗
View Slide
シゴトでココロオドル• 森脇健斗• Wantedlyの新卒二年目エンジニア• フロントエンド好き– Angular書いてた• 最近、Wantedlyのフロントエンド開発環境を刷新した– そのとき導入したImmutable.jsについて話します自己紹介
シゴトでココロオドル• Facebookが開発している不変オブジェクトを扱うライブラリImmutable.jsとはhttps://facebook.github.io/immutable-‐js/
シゴトでココロオドル• オブジェクトのプロパティに代入する代わりに、新しいオブジェクトを返すImmutableimport { Map } from 'immutable'let map1 = Map({ x: 1, y: 2 })let map2 = map1.set('x', 2)assert(map1.get('x') === 1)assert(map2.get('x') === 2)assert(map1 !== map2)
シゴトでココロオドル• 便利なメソッド、効率的な変更、深いオブジェクトも操作しやすい基本的な挙動let map1 = Map({ a: 1, b: 2 })let map2 = map1.merge({ b: 3, c: 4 })alert(map2.get('b') == 3) // true// 変更なければ同じオブジェクトを返すlet map3 = map1.set('a', 1)alert(map3 === map1) // true// 階層深い変更も簡単let map3 = Immutable.fromJS({ a: { b: { c: 1 } } })let map4 = map3.setIn(['a', 'b', 'c'], 2)alert(map4.getIn(['a', 'b', 'c']) === 2) // true
シゴトでココロオドル• List• Set• OrderedMap– IDで検索する機会の多いリストに便利• OrderedSet• Record– Immutableなモデルクラス作れる (後述)便利な型
シゴトでココロオドル• ReactとImmutable.jsは相性いい• 主なメリットは、1. パフォーマンス向上2. ステートの更新が簡単に書ける3. モデルクラス作れるReactと組み合わせるメリット
シゴトでココロオドル• shouldComponentUpdate– Reactのパフォーマンス向上の基本– 再レンダーが必要かどうか返す– 自分や親コンポーネントのstateやpropsが変わった時に呼ばれる– デフォルトは常にtrueパフォーマンス向上shouldComponentUpdate(nextProps, nextState) {return compareSomehow(this, nextProps, nextState)}
シゴトでココロオドル• shouldComponentUpdate– 簡単に• コンポーネント毎に複雑な処理を書きたくない– 高速に• 再レンダーするより変更チェックが速くあるべき– 正確に• 間違っていると、変更が反映されないようになるパフォーマンス向上shouldComponentUpdate(nextProps, nextState) {return this.props.foo !== nextProps.foo}
シゴトでココロオドル• 実際に変更されたかチェックする– 変更がない場合は、同じオブジェクトにしたい• Object.assign などが必要– 変更ないオブジェクトもコピーされるImmutable.jsなしの場合onChange(obj) {let newMap = this.state.mapif (newMap.x !== obj.x) {newMap = Object.assign({}, newMap, { x: obj.x })}this.setState({ map: newMap })}
シゴトでココロオドル• 変更がなければ、自動的に同じオブジェクトを返す• 必要最小限だけ変更される– 変更がないオブジェクトはコピーされない– Object.assignより効率的– 簡潔に書けるImmutable.jsを使用すればonChange(obj) {let newMap = this.state.map.set('x', obj.x)this.setState({ map: newMap })}
シゴトでココロオドル• Reactのpropsを明確化したい– どんなプロパティを期待しているか不明– 型が指定できれば嬉しい• モデルにメソッド持たせたい2. モデルクラスが作れるTickerComponent.propTypes = {ticket: PropTypes.object.isRequired,}TickerComponent.propTypes = {ticket: PropTypes.instanceOf(Ticket).isRequired,}
シゴトでココロオドル• 型を定義できる– フィールドを定義したクラスを作れる• メソッドを定義できる– 継承して、メソッドを持たせることができる– 複雑なフィールド更新をモデルに持たせる• これも非破壊操作になるImmutable.Record
シゴトでココロオドルlib/immutable/Ticket.jsconst _Ticket = Record({id: null,title: '',assignee: new User(),})export default class Ticket extends _Ticket {static fromJS(ticket = {}) {return (new this).merge({id: parseInt(ticket.number),title: ticket.title,assignee: User.fromJS(ticket.assignee),})}isDarkColor() {return parseInt(this.colorCode.substring(1, 7), 16) > 8388607)}}
シゴトでココロオドル• Immutable.js使えば– Reactのパフォーマンスが簡単に向上できる– ステートの更新が簡潔に書ける– Reactで使いやすい独自モデルクラスが定義できるまとめ
シゴトでココロオドル最後に
シゴトでココロオドル• 一緒に働いてくれる仲間を募集しています。一緒にReact書きませんか?https://www.wantedly.com/projects/51709