之所以講這篇文章主要是為了加深對 React hooks 的理解。
因此,先要學習如何抽象自定義 hooks。構建屬于自己的 React hooks 工具庫。
且培養閱讀學習源碼的習慣,工具庫是一個對源碼閱讀不錯的選擇。
現在看下ahooks 是怎么封裝 cookie/localStorage/sessionStorage 的。
cookie
ahooks 封裝了 useCookieState,一個可以將狀態存儲在 Cookie 中的 Hook 。
該 hook 使用了js-cookie這個 npm 庫。為什么用它:
主要就是由于包體積小。壓縮后小于 800 字節。自身是沒有其它依賴的。這對于原本就是一個工具庫的 ahooks 來講是很重要的。而且它擁有更好的兼容性。支持所有的瀏覽器。并支持任意的字符。
除此之外,它還有其他的特點,比如支持 ESM/AMD/CommonJS 方式導入等等。
封裝的代碼并不復雜,先看默認值的設置,其優先級如下:
本地 cookie 中已有該值,則直接取。
設置的值為字符串,則直接返回。
設置的值為函數,執行該函數,返回函數執行結果。
返回 options 中設置的 defaultValue。
const [state, setState] = useState<State>(() => { // 假如有值,則直接返回 const cookieValue = Cookies.get(cookieKey); if (isString(cookieValue)) return cookieValue; // 定義 Cookie 默認值,但不同步到本地 Cookie // 可以自定義默認值 if (isFunction(options.defaultValue)) { return options.defaultValue(); } return options.defaultValue; });
再看設置 cookie 的邏輯 ——updateState方法。
在使用updateState方法的時候,開發者可以傳入新的 options —— newOptions。會與 useCookieState 設置的 options 進行 merge 操作。最后除了 defaultValue 會透傳給 js-cookie 的 set 方法的第三個參數。
獲取到 cookie 的值,判斷傳入的值,假如是函數,則取執行后返回的結果,否則直接取該值。
如果值為 undefined,則清除 cookie。否則,調用 js-cookie 的 set 方法。
最終返回 cookie 的值以及設置的方法。
// 設置 Cookie 值 const updateState = useMemoizedFn( ( newValue: State | ((prevState: State) => State), newOptions: Cookies.CookieAttributes = {}, ) => { const { defaultValue, ...restOptions } = { ...options, ...newOptions }; setState((prevState) => { const value = isFunction(newValue) ? newValue(prevState) : newValue; // 值為 undefined 的時候,清除 cookie if (value === undefined) { Cookies.remove(cookieKey); } else { Cookies.set(cookieKey, value, restOptions); } return value; }); }, ); return [state, updateState] as const; localStorage/sessionStorage
ahooks 封裝了 useLocalStorageState 和 useSessionStorageState。將狀態存儲在 localStorage 和 sessionStorage 中的 Hook 。
兩者的使用方法是一樣的。現在來說說 useLocalStorageState 。
useLocalStorageState就是用來調用 createUseStorageState 方法返回的結果。該方法的入參會判斷是否為瀏覽器環境,以決定是否使用 localStorage,原因在于 ahooks 需要支持服務端渲染。
import { createUseStorageState } from '../createUseStorageState'; import isBrowser from '../utils/isBrowser'; const useLocalStorageState = createUseStorageState(() => (isBrowser ? localStorage : undefined)); export default useLocalStorageState;
我們重點關注一下,createUseStorageState 方法。
先是調用傳入的參數。假如報錯會及時 catch。這是因為:
這里返回的 storage 可以看到其實可能是 undefined 的,后面都會有 catch 的處理。
另外,從這個issue中可以看到 cookie 被 disabled 的時候,也是訪問不了 localStorage 的。stackoverflow也有這個討論。(奇怪的知識又增加了)
export function createUseStorageState(getStorage: () => Storage | undefined) { function useStorageState<T>(key: string, options?: Options<T>) { let storage: Storage | undefined; // https://github.com/alibaba/hooks/issues/800 try { storage = getStorage(); } catch (err) { console.error(err); } // 代碼在后面講解 }
支持自定義序列化方法。沒有則直接 JSON.stringify。
支持自定義反序列化方法。沒有則直接 JSON.parse。
getStoredValue 獲取 storage 的默認值,如果本地沒有值,則返回默認值。
當傳入 key 更新的時候,重新賦值。
// 自定義序列化方法 const serializer = (value: T) => { if (options?.serializer) { return options?.serializer(value); } return JSON.stringify(value); }; // 自定義反序列化方法 const deserializer = (value: string) => { if (options?.deserializer) { return options?.deserializer(value); } return JSON.parse(value); }; function getStoredValue() { try { const raw = storage?.getItem(key); if (raw) { return deserializer(raw); } } catch (e) { console.error(e); } // 默認值 if (isFunction(options?.defaultValue)) { return options?.defaultValue(); } return options?.defaultValue; } const [state, setState] = useState<T | undefined>(() => getStoredValue()); // 當 key 更新的時候執行 useUpdateEffect(() => { setState(getStoredValue()); }, [key]);
最后是更新 storage 的函數:
如果是值為 undefined,則 removeItem,移除該 storage。
如果為函數,則取執行后結果。
否則,直接取值。
// 設置 State const updateState = (value?: T | IFuncUpdater<T>) => { // 如果是 undefined,則移除選項 if (isUndef(value)) { setState(undefined); storage?.removeItem(key); // 如果是function,則用來傳入 state,并返回結果 } else if (isFunction(value)) { const currentState = value(state); try { setState(currentState); storage?.setItem(key, serializer(currentState)); } catch (e) { console.error(e); } } else { // 設置值 try { setState(value); storage?.setItem(key, serializer(value)); } catch (e) { console.error(e); } } };
總結與歸納
對 cookie/localStorage/sessionStorage 的封裝在日常開發中多次用到,其實ahooks 的封裝整體比較簡,但在簡單內容要會才可以。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/128215.html
摘要:顧名思義,確實非常小,它的大小限制為左右,是網景公司的前雇員在年月的發明。是標準中新加入的技術,它并不是什么劃時代的新東西。特性與的接口類似,但保存數據的生命周期與不同。但當頁面關閉后,中的數據就會被清空。 本文最初發布于我的個人博客:咀嚼之味 最近在找暑期實習,其中百度、網易游戲、阿里的面試都問到一些關于HTML5的東西,問題大多是這樣開頭的:你用過什么HTML5的技術呀?...
摘要:的區別及用法是本地存儲,存儲在客戶端,包括和。僅在當前會話下有效,關閉頁面或瀏覽器后被清除。源生接口可以接受,亦可再次封裝來對和有更好的支持。但需要程序員自己封裝,源生的接口不友好。每個最多只能有條,每個長度不能超過。 localStorage、sessionStorage、Cookie的區別及用法 showImg(https://segmentfault.com/img/bVYLlH...
摘要:之前只知道的一些存儲量,過期時間上的區別,今天仔細研究了一下它們用法上的區別。這個限制確保了儲存在中的信息只能讓批準的接受者訪問,而無法被其他域訪問。中所有的名字和值都是經過編碼的,所以必須使用來解碼。屬于永久性存儲。 之前只知道cookie、sessionStorage、localStorage的一些存儲量,過期時間上的區別,今天仔細研究了一下它們用法上的區別。 cookie coo...
摘要:快速上手先說區別數據大小不能超過。可以在后端設置修改,數據僅在本地瀏覽器保存。數據存儲在瀏覽器僅在瀏覽器為關閉的狀態,關閉窗口后數據就會銷毀。默認情況下,屬于當前頁面。 cookie、Sessionstorage、Localstorage快速上手 先說區別 cookie: 數據大小不能超過4KB。 不管是否有需求,cookie數據都會在HTTP請求中攜帶,在瀏覽器和服務器中來回傳遞,...
閱讀 547·2023-03-27 18:33
閱讀 732·2023-03-26 17:27
閱讀 630·2023-03-26 17:14
閱讀 591·2023-03-17 21:13
閱讀 521·2023-03-17 08:28
閱讀 1801·2023-02-27 22:32
閱讀 1292·2023-02-27 22:27
閱讀 2178·2023-01-20 08:28