為什麼不把 Redux Type 設定成 Symbol 呢? #
前端有用 Redux
的工程師都知道,用 Redux
如果需要改變狀態,需要發送行為到 store
裡去,我們常常會寫類似下面的工廠函數:
function someAciton(todo){
return {
type: "SOME_ACTION",
payload: todo
};
}
接下來為了避免 type
有重複問題,會另外建立一個 ActionTypes 清單,裡面會長的類似:
export const ACTION_A = 'ACTION_A';
export const ACTION_B = 'ACTION_B';
export const GOD_DAMN_ACTION = 'GOD_DAMN_ACTION';
...
這時候如果有 100 個 action 你就需要建立 100個 ActionType
。OK, fine.
於是我就想到,既然都要建那麼多個了,有什麼可以比較省事的方法呢?
我就想到 Symbol
。Symbol
是 ES6
引進的,每個 Symbol
都是獨一無二,就算是同一個 Symbol('I_AM_A_SYMBOL')
和另外一個 Symbol('I_AM_A_SYMBOL')
,即使傳入的值一樣,他還是獨一無二。
所以用在上述情境就變成:
export const ACTION_A = Symbol('');
export const ACTION_B = Symbol('');
export const GOD_DAMN_ACTION = Symbol('');
...
在動作函數就可以:
import { ACTION_A } from './ActionTypes.js'
function someAciton(todo){
return {
type: ACTION_A,
payload: todo
};
}
看起來好像很棒?
但如果這方法那麼棒,怎 Redux 一開始沒用這個呢?但他還真的有用過:
在 Redux#4
裡面,作者 gaearon
還曾經那麼使用過,不過他說他後來發現一個問題:
I thought of that, but this kind of screws the replay thing. (AFAIK you can't serialize and then deserialize symbols.) I want to pass them around for devtools, localStorage persistence, etc.
You can't take an array of actions that use symbols, serialise them to JSON, save to localStorage, and later deserialise and replay them in a different browser session.
簡單來說就是不能做 SerDes。複雜一點就是你不能把一大堆動作轉存成陣列,轉為 JSON 存起來,丟到另一個瀏覽器環境,再把它轉換回來。
雖然說技術上應該是可行的,準備一個 Object
將 type
還有 Symbol
互相映射。或者一開始就將 ActionTypes 改寫成:
export default {
ACTION_A: Symbol(''),
ACTION_B: Symbol(''),
ACTION_C: Symbol(''),
};
不過這樣產生另一個問題:只有開發者才知道要怎麼映射。如果要用第三方工具,例如 redux-devtools-extension
,其他開發者根本不知道你的 type
要怎麼映射,而根本無法銜接。
再來就算建立好映射表了,在 Console
上要好好的辨識 Symbol
話,就也要好好取名,例如:
export const ACTION_A = Symbol('');
export const ACTION_B = Symbol('');
這 ACTION_A
和 ACTION_B
在 Console
上都是顯示 Symbol()
。很好,那我們加一些辨識字元:
export const ACTION_A = Symbol('ACTION_A');
export const ACTION_B = Symbol('ACTION_B');
很好,現在在 Console
上就會顯示 Symbol(ACTION_A)
和 Symbol(ACTION_B)
。
那和一開始的比較起來,似乎發現了點問題:這樣根本是多此一舉。
我目前唯一想到可以用的情境,就是 ActionType
已經和其他人撞名了!不過在現代瀏覽器如果有實現 ES6
標準,String.prototype.length
理論值可以到 2^53-1
。
我是想不到哪一種 ActionType
可以在這限制下撞名啦….囧