React Hooks
Hook 是能讓你在函數組件中“鉤入” React 特性的函數。
State Hook
- useState 不能存在于條件判斷語句中,是按照順序記憶的
- Hook 在 class 內部是不起作用的,但是可以使用 hook 取代 class
- 在函數組件中,沒有 this,所以不能分配和讀取 this.state,直接調用 useState Hook
import React, { useState } from 'react'; function example() { // 聲明一個叫做 count 的 state 變量 // React 在重新渲染的時候會記住 count 當前的值,并提供最新的值給我們的函數 // 通過調用 setCount 來更新當前的 count const [count, setCount] = useState('apple'); // 在函數中,直接用 count 讀取 count 的值,而不是通過 this.state.count 的方式。 return ( <p>want an {count}</p> ) }
- 定義 state 變量的時候,等號左邊的名字并不是 React API 的部分,可以自己取名字。這種 JS 語法叫做數組解構。它意味著我們同時創建了 count 和 setCount 兩個變量, count 的值為 useState 返回的第一個值, setCount 是返回的第二個值。它等價于下面代碼:
var fruitStateVariable = useState(0) var count = fruitStateVariable[0] var setCount = fruitStateVariable[1]
- 使用 hook 存儲多個不同的變量,就需要調用 useState() 多次。可以同時給不同的 state 變量去不同的名稱,并且可以單獨更新它們。
function ExampleWithManyStates() { // 聲明多個 state 變量 const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: '學習 Hook' }]);
function handleOrangeClick() { // 和 this.setState({ fruit: 'orange' }) 類似 setFruit('orange'); }
Effect Hook
Effect Hook 可以讓你在函數組件中執行副作用操作
- Effect Hook 可以看做是 componentDidMount, componentDidUpdate, componentWillMount 這三個 React class 生命周期函數的組合
- React 組件中有兩種副作用操作:需要清除的和不需要清除的。
- React 會保存我們傳遞的 effect 函數,并且在執行首次 DOM 渲染 (componentDidMount)和每次更新導致的重新渲染 (componentDidUpdate)都會調用它。
- 傳遞給 useEffect 的函數在每次渲染中都會有所不同,因為每次重新渲染,都會給你新的 effect,替換掉之前的。
- 使用 useEffect 調度的 effect 不會阻塞瀏覽器更新屏幕,這會讓應用看起來更快。而之前的 componentDidMount 或 componentDidUpdate 則是同步執行的
React 的清除機制
- 在 class 中,通常會在 componentDidMount 中設置訂閱,并在 componentDidWillUnmount 中清除它
- effect 中返回一個函數,是 effect 可選的清除機制,每個 effect 都可以返回一個清除函數。React 會在組件卸載的時候執行清除操作。
useEffect(() => {
document.title = `You clicked ${count} times`
}, [count]); // 只有當 count 的值發生改變時,才會重新執行 `document.title` 這一句
這里有一點需要重視,componentWillUnmount 只會在組件被銷毀前執行一次,而 useEffect 里的函數,每次組件渲染后都會執行一遍,包括副作用函數返回的這個清理函數也會重新執行一遍。
useEffect 接受第二個數組類型的參數,僅有在數組中變量發生改變時,才會重新訂閱。如果想執行只運行一次的 effect, 也就是說僅在組件掛載(componentDidMount)和卸載(componentWillUnmount時執行),可以傳遞一個空數組([])作為第二個參數。不過這種用法可能帶來 bug,少用。
其他的 Effect Hooks
除了上文介紹的 useState 和 useEffect,react 還給我們提供了很多有用的 Hooks:
useContext useReducer useCallback useMemo useRef useImperativeMethods useMutationEffect useLayoutEffect
Hook 規則
- 只在最頂層使用 Hook,不要在循環、條件或嵌套函數中調用 Hook。這樣就能確保 Hook 在每一次渲染中都按照同樣的順序被調用。
- 只在 React 函數中調用 Hook,不要在普通的 JavaScript 函數中調用 Hook。
自定義 Effect Hooks
將復用的邏輯抽離出來,哪個組件要用,就在哪個組件里面使用
- 自定義 Hook 是一個函數,其名稱必須以 "use" 開頭,函數內部可以調用其他的 Hook。
- 在兩個組件中使用相同的 Hook 不會共享 state。自定義 Hook 是一種重用狀態邏輯的機制(例如設置為訂閱并存儲當前值),所以每次使用自定義 Hook 時,其中的所有 state 和副作用都是完全隔離的。