先說說 Function Component
- 在每一次
re-render
時, 都會重新 call
一次該function
來創造 react elements- 代表著每一次利用 function 在創造 react elements 時, 擁有著 JavaScript
closure
的特性
- 代表著每一次利用 function 在創造 react elements 時, 擁有著 JavaScript
- 對 Function Component 來說, 當作參數 input 的 props 以及 hook state 都只是
常量
, 它並不知道這些東西是會更動的
Hooks 的內部機制
上一段說了 Function Component 的性質,那為何 hooks 的 useState(或其他 userXXX 系列) 每一次在 re-render 時可以記得上一次的值(包含了 state 以及 setState),而不會重新回傳一個新的
1
2
3
4function FC() {
const [state, setState] = useState(...); // 這裡的 state 和 setState 神奇的存在某個地方
...
}- 也因此必須遵守:
Ensure that Hooks are called in the same order each time a component renders
- 避免將 useXXX 放在 condition block 裡面
useEffect
- useEffect callback 只有在
指定的依賴(也就是第二個參數陣列裡的東西(通常會是 props or state))
改變時, 才會執行- callback 內有用到的 props or state, 盡量確實寫在 dependency array 中, 避免不必要的錯誤
- 當
dependency array 為空
, 代表著- callback 的
本體
只有在 FC 的第一次被 call
時會執行 - callback
return 的 cleanup function
只有在 FC 要被unmount 時
才會執行
- callback 的
- useEffect callback 是在
browers paint 完 UI 後
才執行 (也就是 DOM tree 變更後)- 整個流程
- Component 把當下該顯示的 UI return 給 React
- React 渲染這次的 UI (Update VDOM)
- Browser repaint UI (Commit VDOM to DOM)
- React 處理 useEffect 定義的函數
- (1) run
上一次
useEffect callbackreturn 出來的 cleanup function
- (2) run
這一次
useEffect callback function 的本體
- (1) run
- 整個流程
- useEffect callback 必須回傳
cleanup function or nothing
, 因此callback 不可以掛載 async
(掛載 async 的 function 會回傳Promise
)
Fetch Data pattern
- 包含了
- isLoading
- Cancel: 避免 data 回來 component 已經 unmount, set state 在已經 unmount 的 component 上, 會造成
memory leak
- 一樣用到了
closure
特性
- 一樣用到了
1 | function useData() { |