[Day 3] 本地存取useLocalStorage

今天我們來製作useLocalStorage的custom hook,我們希望他可以像useState一樣製作一個方便控制的localstorage的custom hook
EX:
 
不管今天我們要做測試還是自定義hook,我們都要先思考可能需要哪些功能
  1. state 可以直接拿到我們放進去的value或之後設定的value
  1. 初始值第一次渲染也要設定進去localStorage中
  1. setState可以輕鬆幫我們把我想要的值放進去localStorage中,並且不用再寫一次key,例如:
  1. setState要記得要把他改成String,state拿出來的時候如果是物件或陣列也要記得恢復
 
那我們就開始吧
首先寫好useLocalStorage的function,我們需要傳兩個參數,一個是localStorage的key,一個是要傳入的值,首先key一定會是string,所以我們可以先設定key:string ,initialValue 怎麼辦呢?
我們這時候有一種選擇是直接用any
但這時候就有一個顯而易見的缺陷是,它並沒有準確的定義返回值的型別:
any 允許任意型別。但是我們預期的是,陣列中每一項都應該是一開始輸入的 initialValue 的型別
還有~ 如果碰到每個不知道的都用any了,就乾脆直接用Js寫就好了呀,那怎麼辦呢~
 
這時候我們就要用到typescript好用的<T>泛型拉~
泛型的意思是說,使用者可以自訂型別,後面也會依照型別判斷,很難懂嗎~,用下面範例解釋吧
之後可能還會用到泛型,這個很重要!!! 要記住喔!!!
 
接下來,我們要建立初始值了
  1. 首先,我們用 const item = localStorage.getItem(key)查詢localStorage這個key有沒有值
  1. return item ? JSON.parse(item) : initialValue; 如果有值就回傳當我們的預設值,如果沒有的話,就拿我們的initialValue來當我們的預設值
  1. 最後放進const [storeState, setStoreState] = useState(readInitValue());存取出初始值
  1. 最後用useCallback避免重複渲染
接下來我們來寫setLocalStorage吧
因為我們希望他跟平常useState的setState一樣,所以我們也希望可以傳入兩種形式,一種是一般value,一種是useState的updater方式傳入一個function ()⇒{}
我們有以下兩點要注意
  1. 我們要判斷是不是function ,所以我們用value instanceof Function判斷,如果要使用typeof 也可以,但我更傾向用instanceof
  1. 在setLocalStorage記得先用JSON.stringify()轉換成字串,因為localStorage只能存字串
剩最後一點點了~~
我們還剩兩件事
  1. 第一次渲染就將初始值放進localStorage
  1. storeStatesetLocalStorage回傳出去

完整程式碼:

 
如果不太熟的話,可以用useSessionStorage嘗試看看,我會將useSessionStorage的寫法也放在下面(雖然一模一樣拉…)
 
明天就要開始寫測試了,想試試看的可以今天先寫寫看,明天對答案喔,這個測試我會用三種寫法來教學,敬請期待喔~
 
useSessionStorage.ts