2017年8月16日 星期三

The Necessities of Immutable.js

  • Redux的資料都是不可修改的,一般都是用Object.asign以及Object Spread operator來達成如下:
const state = {
  name: 'Tyler',
  age: 26,
}
const newState = Object.assign({}, state, {
  name: 'Mikenzi'
})
state.name // Tyler
newState.name  // Mikenzi

// and with Object spread
const state = {
  name: 'Tyler',
  age: 26,
}
const newState = {...state, name: 'Mikenzi'}
state.name // Tyler
newState.name  // Mikenzi


  • 但是這種作法會有比較差的Performance,因為要產生一個新的Object,並且把舊的Properties複製過去
  • 改用Immutable.js可以有好很多的Performance
  • Immutable.js支援多種資料結構(List, Stack, Map, OrderedMap, Set, OrderedSet and Record)並且提供額外的API讓你可以對它作操作

Map


  • 首先來看看Map,你可以把它視為JavaScript的一個物件,裡面放的是key-value型態的資料
import { Map } from 'immutable'
const me = Map({
  name: 'Tyler',
  age: 26,
  education: Map({
    elementary: 'Panorama',
    highSchool: 'Pine View',
    college: 'Brigham Young'
  })
})


  • 但是它不能用.(dot)的方式來存取資料
me.name // undefined
me.education.highSchool // Uncaught TypeError: Cannot read property 'education' of undefined


  • 想要存取資料,你必須用get() method
me.get('name') // Tyler
me.get('age') // 26
me.get('education').get('highSchool') // Pine View


  • 巢狀的資料有另一種方式存取,getIn() method
me.getIn(['education', 'highSchool']) // Pine View


  • 想要修改資料的話要用set() method,它會回傳一個新的修改後的Map物件,舊的Map物件不會被修改
// Birthday
const newMe = me.set('age', me.get('age') + 1)
newMe.age // 27
me.age // 26


  • 想要修改巢狀資料也有setIn() method可以使用
const newMe = me.setIn(['education', 'college'], 'N/A')
me.education.college // Brigham Young
newMe.education.college // N/A


List

  • 你可以把List想成JavaScript的array,它提供了array常用的method如push、pop、unshift
import { List } from 'immutable'
const friends = List(['Jake', 'Mikenzi', 'Ean'])


  • 以下列出一些有用的getter methods
friends.get(0) // Jake
friends.get(1) // Mikenzi
friends.first() // 'Jake'
friends.last() // 'Ean'
friends.includes('Ean') // true
friends.includes('Jim') // false
friends.reverse().first() // 'Ean'
friends.size // 3


  • 以下則是修改List資料的例子
const friends = List(['Jake', 'Mikenzi', 'Ean']);
friends.get(0) // Jake
const newFriends = friends.set(0, 'Jacob')
friends.get(0) // Jake
newFriends.get(0) // Jacob


  • 可以用toJS() method將Immutable轉成JS的結構
const friends = Immutable.List(['Jake', 'Mikenzi', 'Ean']);
const newFriends = friends.delete(0)
friends.toJS() // ['Jake', 'Mikenzi', 'Ean']
newFriends.toJS() // ['Mikenzi', 'Ean']

const friends = Immutable.List(['Jake', 'Mikenzi', 'Ean']);
const newFriends = friends.push('Jacob')
friends.toJS() // ['Jake', 'Mikenzi', 'Ean']
newFriends.toJS() // ['Mikenzi', 'Ean', 'Jacob']

const friends = Immutable.List(['Jake', 'Mikenzi', 'Ean']);
const newFriends = friends.unshift('Jacob')
friends.toJS() // ['Jake', 'Mikenzi', 'Ean']
newFriends.toJS() // ['Jacob', 'Jake', 'Mikenzi', 'Ean']


  • 相對的Immutable也有fromJS() method將JS結構轉成Immutable結構,它會遞迴地掃過每個property,若是物件就轉成Map,若是Array就轉成List
const state = fromJS({
  name: 'Tyler',
  age: 26,
  friends: ['Jake', 'Mikenzi', 'Ean'],
  education: {
    elementary: 'Panorama',
    highSchool: 'Pine View',
    college: 'N/A'
  }
})

沒有留言:

張貼留言