Immutable 是我想寫很久的主題,前一份工作時,就大大的踩到關於 immutable 的雷,那時候依靠 google靠解掉這問題,但總該還債的,面試時候也被這個關內給卡到。現代網頁前端不只是要處理畫面更新,更多時間更會處理大量資料處理,不論是重複封裝、更新等等。React 更是把 Imutable 視為重要的開發準則。

react immutable

Immutable mutable data

什麼是 Immutable、mutable,Immutable 稱之不可改變的,mutable 則相反是可以改變的。string、number 都是 immutable 的,簡單講就是不可更改的,舉個例子來說

  • string immutable
    let str = 'Hello, you!!';
    let ianHello = str;
    ianHello += 'ian';

    // not changed
    console.log(str); // Hello, you!!
    console.log(ianHello); // Hello, you!!ian

建立 ianHello 並使用 str 賦值,之後 ianHello 再重新賦值,並不會更動到 str,但 array 就不是這樣了。array 以及 object 使用 call by reference,淺拷貝的做法實現,白話一點講,就是會指導同一個記憶體位置,當你改動資料的時間,是針對指向的那一個記憶體去改,所以才會有連動的狀況。

  • array mutable
    let names = ['ian'];
    let copyName = names;
    copyName.push('peter');

    // changed
    console.log(names); // [ian, peter]
    console.log(copyName); // [ian, peter]

舉下方的例子來說,大致邏輯是依賴兩個陣列資料,驅使更新畫面更新的,呈現問題的使用方法是,點擊複製按鈕,同步兩邊的資料,再點擊任意一個清單的刪除,會發現兩邊畫面居然會連動。

會產生問題的原因是,第一我複製資料的時候,讓兩個陣列變成指向同一個,所以才會兩邊連動畫面更新。

這大致上就是簡單的介紹 immutable 跟 mutable。

React Immutable

React 有提到 state 的更新,都必須要是 immutable,當你有使用到 useState 或是 pureComponent、shouldComponentUpdate,你就會發現問題。下面範例就是 mutable 的更新 state。

  • mutable setState
    const value = ref.current.value;
    names.push(value);
    setNames(names);

結果就是沒辦法觸發 update component,因為 useState 就有自帶了 shallowEqual,同一個記憶體位置去比較有無更新,當然恆等於,所以這個案例,你怎們加入都無法更新畫面。

  • immutable setState
    setNames(names => [...names, value])

react optimizing-performance

redux reducers immutablejs

心得

記得剛轉前端工作的時候,被這問題卡了一下午,最後是靠 stackoverflow slice,來解決問題。以前遇到問題都是找到解法就結束了,但說實在沒搞懂原因,這樣遲早還是得回頭還債的。

勉勵一下自己,要求慎解啊!

一樣有問題、或是錯誤,歡迎留言,感謝閱讀。