隻在最頂層使用Hook,不在條件、循環或者嵌套函數中使用Hook
隻在React函數式元件或自定義Hook中使用Hook
Hook存儲在元件的私有屬性中__hooks_list數組中。讀取和存儲都依賴currentIndex,如果hook的執行順序改變,currentIndex擷取的hook可能是完成錯誤的。

Effect Hook 可以在函數元件中執行一些具有side effect(副作用)的操作
回調函數: 在元件第一次render和之後的每次update後運作,React保證在DOM已經更新完成後才會回調。
狀态依賴(數組): 當配置了狀态依賴項後,隻有檢測倒配置狀态變化後,才會調用回調函數。
useEffect的第一個參數可以傳回一個函數,這個函數會在頁面更新渲染後,執行下次useEffect之前調用。這個函數是對上一次調用useEffect進行清理。
執行上面的代碼,并點選幾次按鈕,會得到下面的結果:
如果加上浏覽渲染的情況,結果應該是這樣的:
那為什麼浏覽器在渲染完後,再執行清理的方法還能找到上一次的state呢?原因很簡單,我們再useEffect中傳回的是一個函數,形成了一個閉包,這能保證我們上一次執行函數存儲的變量不會被銷毀和污染。
舉例會更好了解:
componentDidMount等價于useEffect的回調,僅在頁面初始化完成後執行一次。當useEffect的第二個參數傳入一個空數組時就可以實作這種效果。
官方不推薦這種寫法,因為可能會導緻一些錯誤。
不像componentDidMount或者componentDidUpdate,useEffect中使用的effect并不會阻止浏覽器渲染頁面。這讓頁面渲染看起來更加流程。
紅圈中是同步操作
useLayoutEffect和useEffect類似,但不同的是:
useEffect不會阻塞浏覽器的重繪
useLayoutEffect會阻塞浏覽器的重繪。如果需要手動修改dom,推薦使用useLayoutEffect。因為如果在useEffect中更新dom,useEffect不會阻塞浏覽器重繪,使用者可能會看到因為更新導緻的閃爍。
使用useRef Hook,你可以輕松擷取dom的ref。
useRef不僅僅可以用來當作擷取dom的ref。還可以通過useRef産生的ref的current屬性的可變性,用它來儲存任意值。
componentDidUpdate就相當于第一次調用的useEffect,借助useRef生成一個辨別,來記錄是否為第一次執行:
在React中,性能優化點在于:
調用setState,就會觸發元件的重新渲染,不論state是否變化
父元件更新,子元件也會更新
基于以上兩點,useCallback和useMemo就是解決性能問題的殺手锏。
useCallback和useMemo的異同:
共同點:
僅僅是依賴資料發生變化時,才會重新計算結果,起到緩存作用。
兩者差別:
useMemo計算結果是return回來的值,主要用于緩存計算結果的值。應用場景: 需要計算的狀态。
useCallback計算結果是函數,主要用于緩存函數。
useCallback傳回的是緩存的函數,最簡單的用法:
const fnA = useCallback(fnB, [a]);
當依賴 a 變更時,會傳回新的函數。我們無法很好的判斷傳回函數是否變更,可以借助ES6新增的資料類型Set來判斷,具體如下:
每次修改count,set.size都會+1,這說明useCallback依賴變量count變化時,會傳回新的函數。而val變化時,set.size無變化,說明傳回的是緩存的函數。
知道useCallback特點後,有什麼作用呢?
使用場景:有一個父元件,包含子元件,子元件接收一個函數作為peops。通常而言,如果父元件更新了,子元件也會執行。但大多數情況下,更新是沒有必要的。我們可以借助useCallback來傳回函數,然後把這個函數作為props傳遞給子元件;這樣,子元件就能避免不必要的更新。
我們先來看個反例:
這裡建立了兩個state,然後通過expensive函數,執行一次昂貴的計算,拿到count對應的某個值。我們可以看到:無論是修改count還是val,由于元件的重新渲染,都會觸發expensive的執行。但是這裡的昂貴計算隻依賴于count的值,在val修改的時候,是沒有必要再次計算的。
在這種情況下,我們就可以使用useMemo,隻在count的值修改時,執行expensive計算:
上面我們可以看到,使用useMemo來執行昂貴的計算,然後将計算值傳回,并且将count作為依賴值傳遞進去。這樣,就隻會在count改變的時候觸發expensive執行,在修改val的時候,傳回上一次緩存的值。
同時也可以用來持久化一個執行函數,避免子元件的重複渲染,例如: