如何使用React Hook
class組件和函數組件
我們希望編寫代碼的時候,盡可能將整塊可復用的部分封裝起來。這樣可以一定程度提高代碼的內聚性,將其耦合性,使得程序開發變得更加可維護。通常情況下,我們將代碼塊抽離成組件來實現封裝。在React中,實現組件封裝有兩種方式,分別是通過class方式以及函數組件方式。
class方式:
class List extends React.Component {constructor(props) {super(props)}render() {const { item } = this.propsreturn <h1>{item}</h1>} }函數方式:
function List(props) {const { item } = propsreturn <h1>{item}</h1> }從上面代碼中可以看出,函數組件相比于class組件要簡單很多。但是函數組件1. 沒有生命周期。 2. 沒有state和setState,只能接收props這就導致函數組件只能實現十分基礎和簡單的功能,稍微復雜一點的功能只能使用class組件來實現。
使用class組件有一個不太好的地方,因為生命周期的原因,導致狀態邏輯常常發生割裂。例如,組件常常在 componentDidMount 和 componentDidUpdate 中獲取數據。但是,同一個 componentDidMount中可能也包含很多其它的邏輯,如設置事件監聽,而之后需在 componentWillUnmount 中清除。相互關聯且需要對照修改的代碼被進行了拆分,而完全不相關的代碼卻在同一個方法中組合在一起。如此很容易產生 bug,并且導致邏輯不一致[1]。
由于React工具的編程理念就是在倡導函數式編程[2],但目前的函數組件功能太簡單,沒有辦法滿足更復雜的開發需求,通過引入Hook可以增強函數組件的能力,并且規避class組件不好的地方。
State Hook
默認函數組件是沒有state的,函數組件是一個純函數,執行完即銷毀,無法存儲state。我們如果想要擴展函數組件的功能,可以使用"鉤"的辦法,把state功能"鉤"到純函數中[3]。因此稱之為State Hook。
關于State Hook最基本使用方式,可以看這個參考文檔:使用 State Hook
Effect Hook
函數組件第二個問題是沒有生命周期,和上面介紹的通過使用State Hook來向函數組件引入state一樣,我們可以通過Effect Hook向函數組件引入生命周期功能。
關于Effect Hook最基本使用方式,可以看這個參考文檔:使用 Effect Hook
在閱讀文檔的時候,你可能會像我開始的時候一樣,對副作用這個詞一頭霧水,這里,我再對副作用這個概念做一點個人理解的簡要說明。首先要明確純函數這個概念,滿足以下幾點要求的函數,我們就稱之為純函數[5]:
函數組件原本是純函數,但使用Effect Hook之后,它可能會引起程序狀態發生改變,破壞了函數組件純函數的特點。因此我們會說,使用Effect Hook有的時候會帶來副作用。比如你在函數組件生命周期里面定義了一個全局定時任務,函數組件銷毀的時候卻不銷毀這個全局定時任務,這樣就破壞了純函數的特點,改變了整體程序狀態。
最后我再說一點參考文檔使用 Effect Hook中沒有強調顯著說明的地方。useEffect默認是模擬的DidMount和DidUpdate,比如說你寫成這樣的形式:
useEffect(() => {console.log('我被執行啦!') })第一次是組件渲染的時候執行DidMount會打印該條語句,之后組件更新是執行DidUpdate組件更新又會打印該條語句。如果你只想要DidMount而不想要DidUpdate要寫成這樣的形式:
useEffect(() => {console.log('我被執行啦!') }, [])第二點是如果寫成下面這種形式,每一次組件在執行更新時,都會執行前一步的卸載。useEffect會在調用一個新的 effect 之前對前一個 effect 進行清理。
useEffect(() => {console.log('我被執行啦!')return () => {console.log('我被卸載啦!')} })useContext
通過上述兩個Hook的使用,解決了函數組件最大的通點,大大增強了函數組件的能力。在官方文檔的基礎Hook中還有一個Hook是useContext。
它的作用就是獲得父組件傳遞的數據。詳情可以參考useContext
useReducer
useReducer是useState的替代方案,而不是替代Redux的。想了解關于Redux的更多內容可以參考: Redux 入門
關于useReducer,官方文檔是這么說的:
在某些場景下,useReducer 會比 useState 更適用,例如 state 邏輯較復雜且包含多個子值,或者下一個 state 依賴于之前的 state 等。并且,使用 useReducer 還能給那些會觸發深更新的組件做性能優化,因為你可以向子組件傳遞 dispatch 而不是回調函數 。
自定義Hook
當我們想在兩個函數之間共享邏輯時,我們會把它提取到第三個函數中。而組件和 Hook 都是函數,所以也同樣適用這種方式。自定義 Hook 是一個函數,其名稱以 “use” 開頭,函數內部可以調用其他的 Hook。其內部可以使用useState useEffect獲取其他Hooks,并且可以自定義返回結果,格式不限。 關于自定義Hook具體使用可以參考:自定義 Hook
Hook使用規范
關于Hook使用規范,可以參考:Hook 規則。簡單來說,一共兩條:
- 不要在循環,條件或嵌套函數中調用 Hook
- 只在 React 函數中調用 Hook
只看文檔可能不太清楚,我這里再強調一下為什么一定不要在嵌套里使用Hook。因為函數組件是一個函數,有用完即銷毀的特點。那些保存的變量會被清空,是沒有記憶性的。所以,如果你用了判斷語句,是不能保證每次useState賦值是一致的。
參考資料
[1] Hook 簡介
[2] 為什么 React 現在要推行函數式組件,用 class 不好嗎?
[3] 使用 State Hook
[4] 使用 Effect Hook
[5] 什么是純函數?它函數式編程的基礎
[6] useContext
[7] Redux 入門
[8] useReducer
[9] 自定義 Hook
[10] Hook 規則
總結
以上是生活随笔為你收集整理的如何使用React Hook的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS设置样式时,鼠标移动到div上,发
- 下一篇: React Hook基本使用踩坑指南