寫 React 的時候常常聽到 immutable,什麼是 immutable ?

Hyman Chen
ReactMaker
Published in
5 min readJun 20, 2018
“A young man working on a laptop while seated on a ledge in a city during sunset” by Avi Richards on Unsplash

Immutable 中文翻譯為不變的,簡單來說,我們每次操作 React state 的時候,原本的 state 是不變的,有變更到的物件記憶體位置要與原本的記憶體位置不同。

說起來很虛幻,這邊先從更基本的講起,在還沒有學到 React 之前,我們在寫 javascript 的時候常常會搞不懂 js 的傳值與傳址。

const a = { id: 1, name: 'jack'};
const b = a;
b.name = 'kant';
console.log(a.name); //kant
console.log(b.name); //kant

上面這個範例很明顯我們想要複製一份相同的內容,可是由於 javascript 語言的特性,只會把記憶體的位置指定過去,所以修改到了原本的內容。

我們為了要避免掉這樣的事情發生,所以通常會使用 Object.assign 或是 es6 裡面的解構功能來複製,例如以下的程式碼

const a = { id: 1, name: 'jack' };
const b = Object.assign({}, a);
// or const b = {...a};
const b.name = 'kant';
console.log(a.name); //jack
console.log(b.name); //kant

為什麼要在 React 裡面做 Immutable 這種事情?

這邊就要講到上一篇,我建議大家可以使用 PureComponent 來提升效能的這件事情,我們在使用 PureComponent 的時候他會去檢查傳入的 Props 有沒有變動,如果沒有變動的話,就不會觸發渲染。

範例的程式我放在這邊,各位可以點進去玩玩看,很多初學 React 的人常常會想要在列表裡面新增一個項目,可是修改完 state 以後都沒有反應。

那是因為他們在 setState 的寫法是長這樣,直接修改了 state 以後去執行 setState , 但是因為這樣修改的記憶體位置是一樣的,所以 PureComponent 就不會觸發 render 。

你會發現如果用 PureComponent 怎麼點選畫面都不會改變,這是因為我們沒有把 state 做 immutable。各位可以想一下要怎樣修改才可以正常添加一筆資料進去。

那要怎樣修改才是immutable?我們可以使用es6 的解構功能來做。

this.setState({ 
list: [
...this.state.list,
{ id: Math.random(), name: randomStr.genreate(4) }
]
});

像上面範例,我就把原本的 state 淺拷貝了一份出來,並且給予了不同的記憶體位置,這樣就可以正確 render 了。

有一件很有趣的事情,那就是如果你把 PureComponent 改成普通的 Component ,即使不用 immutable 也可以正常 render ,所以 immutable 這個概念只在 PureComponent 才發生。

可以幫助你做 Immutable 的一些套件

我們都知道使用 Object.assign 或是 es6 解構的時候只能對第一層拷貝,要是我們資料結構比較複雜裡面的東西就不會被拷貝,到時候就不會觸發渲染。

const a = { b: { c: 1344 } };
const b = {...a);
b.b.c = 2000;
console.log(a.b.c) //2000

像是這種範例,我們如果沒辦法把 state 扁平化,那就必須依賴套件了,主流的套件是臉書公司出的 Immutable.js ,最近新出來的就是 Mobx 作者出的 Immer.js。

Immutable.js

immutability-helper.js

Immer.js

哪種比較好用? 我自己是覺得 Immutable 跟 immutability-helper 兩種學習曲線比較高一點點,比較不好學,因為 api 文件必較多,你要去記住一些資料更新的語法,反而是新出來的 Immer.js 比較好懂,可以直接對料做修改之後產出新的 state。在學習 React 的時候搞懂 Immutable 是很重要的,它可以讓你之後的程式減少互相干擾的機會,讓你除錯的時候邏輯清晰。

--

--