紀錄一些比較少用到的 hooks 或函式,有些是在課程
https://www.udemy.com/course/react-the-complete-guide-incl-redux/?couponCode=LETSLEARNNOW 中學到
可以想像成是一個全域變數,被這個 context 的 provider 包覆住的元件(包含元件內的子元件)都可以使用這裏面的內容,最常被使用在是傳入一些 state 和修改 state 的函式,可以用來避免 props drilling的情況。
props drilling 的情況就是假如有一個變數或函式要在比較內層的子物件中使用,可能就必須透過 props 來一層層傳遞到下層,即使中間這些傳遞的物件並沒有使用到這裏面的變數或函式。這樣不僅不直觀,也會讓整個 props 變的冗長。
首先,要先創建一個 context ,一般會建議新增一個檔案然後把這個 context export 出去。
例如:
接下來,將這個 context import 後,在最外層的地方使用 provider 包覆,例如:
記得要加入 provider 和 value,如果不加 provider 可能會讀到預設值,不加 value 會讀到 undefined。
參考: https://react.dev/reference/react/useContext
接下來,內部的元件如果要使用這個 context ,有兩種方法:
來使用 context 的內容
此處透過解構來使用,當然要寫成 useContext 獲取整個 CartContext 的內容再透過
.addItemToCart
使用也可以
記住在 Consumer 內必須有一個函式回傳內容,而 cartCtx 就是獲取的 context。
可以看到為了使用會變得比較冗長,因此一般還是建議使用 useContext。
可以想成用來操作比較複雜的邏輯時可以使用的 state,舉例來說:
首先要宣告一個 function ,這個 function 是用來定義當接收到 action 時,應該做甚麼動作,在這個範例中就是 counterReducer。
使用時類似 useState,useReducer 包含兩個參數,第一個是前面定義行為的function,第二個是初始值。
接下來,假如想使用這個 reducer(例如按下按鈕 +1):
dispatch function 類似於 setState,但傳入的是要執行的行為,如果透過 useState,可能必須分開寫成三個函式,分別是:
儘管實際寫的程式碼沒有變少,但可以讓程式碼的可讀性提高。
提到 memo 之前,要先說明 react 中各種元件更新的方法:
首先,component 中如果又有其他 custom component,這樣就會產生樹狀的結構,舉例來說:
這張圖中, App component 又用了兩個 custom component,而這些 custom component 又用了其他的 compnent。
假設此時 APP component 中的 state 變動,這會讓 APP component 和他的兩個子元件重新渲染。
但考慮到另一個情況,假如 App component 的變動實際上和他的子元件沒有關係,但這些元件還是會被重新渲染,這明顯不太符合效益。
也因此出現了 memo,這是 react 中提供的函式,用法是:
實際上就是用 memo 把原本的 function component 包起來而已,使用 memo 的function component 會在 parent component 重新渲染時檢查自己的 props 是否被變動,如果有變動,function component 才會重新被執行。
聽起來那好像把所有 component 都用 memo 包起來效能會最好,但實際上,用了 memo 相當於每次都要對 props 進行比對,實際上也會對效能造成影響,因此使用 memo 時要注意下面幾點:
前面講到 memo 可以避免在 props 沒有改變時還重新渲染的情況,但有一點要注意,就是如果傳入的 props 是一個函式,那這個函式會在重新被渲染時再次創建,這會導致其 child component 即使加上了 memo 還是被重新渲染,因為函式記憶體位置變了。
要解決這個問題,可以透過 useCallback,使用方法類似 useEffect:
這個 function 在 a,b 沒有被改變時不會被重新創建,記憶體位置也不會變動,如此一來就可以避免前面提到的問題。
useMemo 是用來阻止複雜的運算,以下是一個範例,假設下面的程式碼是在一個 component 內,n 是某個 props的內容:
如果這個 complex_function 的運算很複雜,當然會希望避免重複運算,因此可以透過 useMemo:
和 useCallback、useEffect 相同,useMemo 第一個參數是一個有回傳值的函式,第二個則是 dependency array,裡面的內容有變才會被重新運算。
這是一個在 react-dom 中的函式,最常被應用的地方是彈窗,語法為:
這允許這個 component 出現在 dom-tree 的任何地方,而不只是包含在當前這個 component。
舉例來說,如果想要有一個彈出視窗出現在最外面,可以使用:
這就代表把 ModalContent 這個 component 插入到元素中(如果要插入在別的位置,可以用 getElementByID)。
另外可以搭配 dialog 標籤使用,例如
這會把這個 component 插入到 modal 這個 dom 內,並且可以透過 showModal 把不能訪問的部分變暗。