為什麼會有 Hook
介紹之前,首先要給大家說一下
Hooks
的元件
React
,一種是
建立方式
,一種是
類元件
元件,并且
純函數
團隊希望,元件不要變成複雜的容器,最好隻是資料流的管道。開發者根據需要,組合管道即可。也就是說元件的
React
應該是
最佳寫法
,而不是類。。
函數
但是我們知道,在以往開發中
類元件
和
純函數元件
的差別是很大的,純函數元件有着類元件不具備的多種特點,簡單列舉幾條
- 純函數元件
沒有狀态
- 純函數元件
沒有生命周期
- 純函數元件
沒有this
- 隻能是
純函數
這就注定,我們所推崇的函數元件,隻能做
UI
展示的功能,涉及到狀态的管理與切換,我們不得不用
類元件
或者
redux
,但我們知道類元件的也是有缺點的,比如,遇到簡單的頁面,你的代碼會顯得很重,并且每建立一個類元件,都要去繼承一個
React執行個體
,至于
Redux
,更不用多說,很久之前
Redux
的作者就說過,“
能用React解決的問題就不用Redux
”,等等一系列的話。關于
React
類元件
redux
的作者又有話說
- 大型元件很難
和拆分
,也很重構
。難測試
- 業務邏輯分散在元件的各個方法之中,導緻
或重複邏輯
。關聯邏輯
- 元件類引入了複雜的程式設計模式,比如
render
和props
。高階元件
類元件雖然功能齊全卻很重,純函數很輕便卻有上文幾點重大限制,是以團隊設計了
React
,
React Hooks
就是加強版的函數元件,我們可以完全不使用
React Hooks
,就能寫出一個全功能的元件
class
Hook 解決了什麼問題
解決了我們五年來編寫和維護成千上萬的元件時遇到的各種各樣看起來不相關的問題。無論你正在學習
Hook
,或每天使用,或者更願嘗試另一個和
React
有相似元件模型的架構,你都可能對這些問題似曾相識。
React
React
沒有提供将可複用性行為“附加”到元件的途徑(例如,把元件連接配接到
store
)。如果你使用過
React
一段時間,你也許會熟悉一些解決此類問題的方案,比如
render
props
和
高階元件
。但是這類方案需要重新組織你的元件結構,這可能會很麻煩,使你的代碼難以了解。如果你在
React DevTools
中觀察過
React
應用,你會發現由
providers
,
consumers
,
高階元件
,
render props
等其他抽象層組成的元件會形成“
嵌套地獄
”。盡管我們可以在
DevTools
過濾掉它們,但這說明了一個更深層次的問題:
React
需要為共享狀态邏輯提供更好的原生途徑。
你可以使用 Hook 從元件中
提取狀态邏輯
,使得這些邏輯可以單獨測試并複用。
Hook
使你在無需修改元件結構的情況下
複用狀态邏輯
。 這使得在
元件間
或
社群内
共享
Hook
變得更便捷。
官方提供了哪些 Hook
如果你剛開始接觸,那麼可能需要先自行檢視
Hook
官方文檔
React
- 基礎 Hook
-
useSstate
-
useEffect
-
useContext
-
- 額外的 Hook
-
useReducer
-
useCallback
-
useMemo
-
useRef
-
useImperativeHandle
-
useLayoutEffect
-
useDebugValue
-
這篇文章的重點不會對官方
Hook
的使用做過多的講解,當然,想要用好
Hook
,首先要先把官方提供的這些
Hook
學明白,才能在項目開發的時候如魚得水,其次就是做一些自定義
Hook
的封裝,用來提高開發效率
當然,項目開發總不能遇到一個功能就去封裝一個自定義,這裡為大家推薦兩個比較好用的
Hook
庫:
Hooks
aHooks
,這兩個庫使用在項目開發中真的能大大提高
react-use
,可以毫不誇張的說能夠降低你的
開發效率
的業務代碼,告别
50%
996
什麼是 ahooks
官網: https://ahooks.js.org/zh-CN
是一個
ahooks
庫,緻力提供常用且高品質的 Hooks。 在使用之前,你需要掌握
React Hooks
及
React
基礎用法。
React Hooks
是由螞蟻
ahooks
團隊、
umi
團隊以及
淘系 ice
團隊共同建設的
阿裡體育
工具庫。
React Hooks
基于
ahooks
的邏輯封裝能力,提供了大量常見好用的
React Hooks
,可以極大降低代碼複雜度,提升開發效率。
Hooks
緻力成為和
ahooks
一樣的
antd/fusion
基礎設施,幫助開發者在邏輯層面省去大量的重複工作。
React
安裝
# 安裝依賴
npm i ahooks --save
# 使用 Hooks
import { useRequest } from 'ahooks';
有哪些實用 Hooks
- 🔥異步請求
-
— 一個強大的管理異步資料請求的useRequest
。Hook
-
- 🔥table
-
— 封裝了常用的useAntdTable
與antd Form
關聯邏輯,并且同時支援antd Table
。antd V3 和 V4
-
— 封裝了常用的useFusionTable
與Fusion Form
關聯邏輯。Fusion Table
-
- 🔥視圖類的
-
&useDrag
— 一對幫助你處理在拖拽中進行資料轉移的useDrop
hooks
-
— 一個幫助你管理清單狀态,并能生成唯一useDynamicList
的key
。Hook
-
— 常見關聯useSelections
邏輯封裝,支援多選,單選,全選邏輯,還提供了是否選擇,是否全選,是否半選的狀态。checkbox
-
— 提供虛拟化清單能力的useVirtualList
,用于解決展示海量資料渲染時首屏渲染緩慢和滾動卡頓問題。Hook
-
- 🔥副作用
-
— 用來處理防抖值的useDebounce
。Hook
-
— 用來處理防抖函數的useDebounceFn
。Hook
-
— 一個可以處理 setInterval 的useInterval
。Hook
-
— 用來處理節流值的useThrottle
。Hook
-
— 用來處理節流函數的useThrottleFn
。Hook
-
— 一個可以處理useTimeout
計時器函數的 Hook。setTimeout
-
- 🔥生命周期
-
— 為useDebounceEffect
增加防抖的能力。useEffect
-
— 隻在元件useMount
時執行的 hook。mount
-
— 為useThrottleEffect
增加節流的能力。useEffect
-
— 在useTrackedEffect
的基礎上,追蹤觸發 effect 的依賴變化。useEffect
-
— 隻在元件useUnmount
時執行的 hook。unmount
-
— 擷取目前元件是否已經解除安裝的useUnmountedRef
,用于避免因元件解除安裝後更新狀态而導緻的記憶體洩漏hook
-
— 強制元件重新渲染的 hook。useUpdate
-
— 一個隻在依賴更新時執行的useUpdateEffect
hook。useEffect
-
— 一個隻在依賴更新時執行的useUpdateLayoutEffect
Hook。useLayoutEffect
-
- 🔥狀态
-
— 一個同步元件内部狀态和useUrlState
參數的 hook。query
-
— 優雅的管理useBoolean
值的 Hook。boolean
-
— 使元件的狀态即可以自己管理,也可以被外部控制useControllableValue
-
— 一個可以将狀态持久化存儲在useCookieState
中的 Hook 。cookie
-
— 一個用于管理倒計時的 Hook。useCountDown
-
— 一個可以管理useCounter
的 Hook。count
-
— 優雅的管理狀态變化曆史,可以快速在狀态變化曆史中穿梭 - 前進跟後退。useHistoryTravel
-
— 一個可以将狀态持久化存儲在useLocalStorageState
中的 Hook 。localStorage
-
— 一個可以管理useMap
類型狀态的 Hook。Map
-
— 一個可以管理網絡連接配接狀态的 Hook。useNetwork
-
— 儲存上一次渲染時狀态的 Hook。usePrevious
-
— 一個可以将狀态持久化存儲在useSessionStorageState
中的 Hook。sessionStorage
-
— 一個可以管理useSet
類型狀态的 Hook。Set
-
— 管理useSetState
類型object
的 Hooks,用法與state
元件的class
基本一緻。this.setState
-
— 用于在兩個狀态值間切換的 Hook。useToggle
-
— 用于處理useWebSocket
的 Hook。WebSocket
-
— 幫助開發者排查是什麼改變導緻了元件的useWhyDidYouUpdate
。rerender
-
- 🔥Dom 相關
-
— 優雅的管理目标元素外點選事件的 Hook。useClickAway
-
— 可以擷取頁面可見狀态的 Hook。useDocumentVisibility
-
— 優雅使用useEventListener
的 Hook。addEventListener
-
— 常見表單控件(通過useEventTarget
擷取表單值) 的e.target.value
跟onChange
邏輯封裝,支援自定義值轉換和重置功能。value
-
— 一個用于動态地向頁面加載或解除安裝外部資源的 Hook。useExternal
-
— 用于設定與切換頁面useFavicon
。favicon
-
— 一個用于處理useFullscreen
dom
的 Hook。全屏
-
— 一個用于追蹤useHover
元素是否有dom
的 Hook。滑鼠懸停
-
— 一個用于判斷useInViewport
元素是否在dom
的 Hook。可視範圍之内
-
— 一個優雅的管理useKeyPress
和keyup
鍵盤事件的 Hook,支援鍵盤keydown
,定義鍵盤事件的組合鍵
和key
别名輸入 。keyCode
-
— 一個跟蹤useMouse
的 Hook。滑鼠位置
-
— 擷取響應式資訊。useResponsive
-
— 擷取元素的滾動狀态。useScroll
-
— 一個用于監聽useSize
節點尺寸變化的 Hook。dom
-
— 實時擷取使用者目前選取的文本内容及位置。useTextSelection
-
— 用于設定頁面标題的 Hook。useTitle
-
- 🔥進階 Hook
-
— 是useCreation
或useMemo
的替代品,確定執行個體不會被重新建立。useRef
-
— 多元件間事件通知。useEventEmitter
-
— 給異步函數加鎖,防止重複調用。useLockFn
-
— 持久化usePersistFn
的 Hook。function
-
— 提供一種資料響應式的操作體驗,定義資料狀态不需要寫 useState , 直接修改屬性即可重新整理視圖。useReactive
-
— 用法與useSafeState
完全一樣,但是在元件解除安裝後異步回調内的React.useState
不再執行,避免因元件解除安裝後更新狀态而導緻的記憶體洩漏。setState
-
什麼是 react-use
是一個國外大佬開發,目前 start 25.9K
,github 位址: https://github.com/streamich/react-use
安裝
# 安裝依賴
npm i react-use --save
# 使用 Hooks
import { useBattery } from 'react-use';
有哪些實用 Hooks
- 🔥傳感器
-
— 跟蹤裝置電池狀态。useBattery
-
— 跟蹤使用者裝置的地理位置狀态。useGeolocation
-
anduseHover
— 跟蹤滑鼠懸停某個元素的狀态。useHoverDirty
-
— 跟蹤使用者是否處于非活動狀态。useIdle
-
,useKey
,useKeyPress
, 和useKeyboardJs
— 追蹤按鍵。useKeyPressEvent
-
— 跟蹤頁面導航欄的位置狀态。useLocation
-
— 跟蹤 CSS 媒體查詢的狀态。useMedia
-
— 跟蹤連接配接的硬體裝置的狀态。useMediaDevices
-
— 跟蹤裝置的運動傳感器的狀态。useMotion
-
anduseMouse
— 跟蹤滑鼠位置的狀态。useMouseHovered
-
— 跟蹤使用者的網際網路連接配接狀态。useNetwork
-
— 跟蹤裝置螢幕方向的狀态。useOrientation
-
— 當滑鼠離開頁面邊界時觸發。usePageLeave
-
— 跟蹤 HTML 元素的滾動位置。useScroll
-
— 跟蹤 HTML 元素的次元。useSize
-
— 檢測使用者何時開始輸入。useStartTyping
-
— 跟蹤 視窗 滾動位置。useWindowScroll
-
— 跟蹤 視窗 尺寸。useWindowSize
-
- 🔥使用者界面
-
— 播放音頻并公開其控件。useAudio
-
— 當使用者點選目标區域外時觸發回調。useClickAway
-
— 動态調整 CSS。useCss
-
anduseDrop
— 跟蹤檔案,連結和複制粘貼。useDropArea
-
— 全屏顯示元素或視訊。useFullscreen
-
— 從文本字元串合成語音。useSpeech
-
— 播放視訊,跟蹤其狀态,以及公開播放控件。useVideo
-
— UI 的複雜等待管理。useWait
-
- 🔥動畫效果
-
— 在每個useRaf
上重新呈現元件。requestAnimationFrame
-
— 根據彈簧動力學随時間插入數字。useSpring
-
— 逾時後傳回useTimeout
。true
-
— 重新渲染元件,同時補間 0 到 1 之間的數字。useTween
-
— 傳回一個回調,在調用時重新呈現元件。useUpdate
-
- 🔥副作用
-
— 解析一個useAsync
函數。async
-
— 異步函數的狀态管理。useAsyncFn
-
—useAsyncRetry
帶有useAsync
方法。retry()
-
— 當使用者嘗試重新加載或關閉頁面時顯示浏覽器警報。useBeforeUnload
-
— 将文本複制到剪貼闆。useCopyToClipboard
-
— 防抖函數。useDebounce
-
— 設定頁面的useFavicon
。favicon
-
— 管理useLocalStorage
中的值。localStorage
-
— 鎖定useLockBodyScroll
元素的滾動。body
-
— 管理useSessionStorage
中的值。sessionStorage
-
anduseThrottle
— 節流一個函數。useThrottleFn
-
— 設定頁面标題。useTitle
-
- 🔥生命周期
-
— 僅運作一次的修改後的useEffectOnce
。useEffect
-
— 訂閱事件。useEvent
-
— 調用useLifecycles
和mount
回調。unmount
-
— 跟蹤元件是否已挂載。useRefMounted
-
— 僅在安裝元件時解析usePromise
。promise
-
— 在元件經曆生命周期時登入控制台。useLogger
-
— 調用useMount
回調。mount
-
— 調用useUnmount
回調。unmount
-
— 僅在更新時運作一個useUpdateEffect
。effect
-
— 運作一個useDeepCompareEffect
通過深度比較其依賴項。effect
-
- 🔥狀态
-
—createMemo
的工廠鈎子。memoized hooks
-
— 傳回狀态useGetSet
而不是原始狀态。getter get()
-
— 就像useGetSetState
和useGetSet
有個孩子。useSetState
-
— 跟蹤useObservable
的最新值。Observable
-
— 建立類似useSetState
的this.setState
方法。setState
-
anduseToggle
— 跟蹤布爾值的狀态。useBoolean
-
anduseCounter
— 跟蹤數字的狀态。useNumber
-
— 跟蹤數組的狀态。useList
-
— 跟蹤對象的狀态。useMap
-
以上介紹的兩個庫,運用在項目開發中可以說是能夠減少你的
Hooks
業務代碼,真的告别
50%
,利用更多的時間來學習新的知識,不要做業務開發的傀儡 🎃
996
當然在我們平時開發過程中,肯定會遇到一些項目中業務邏輯之類的封裝或者是以上兩個 Hooks 庫沒有涉及到的場景,這種情況下就需要自己去
自定義 Hook
了,千萬要記住: 不要因為自己的一時偷懶直接複制代碼,複制一時爽,重構火葬場 🔥🔥🔥
自定義 Hook
官方介紹:自定義隻是将兩個函數之間一些共同的代碼提取到單獨的函數中。自定義
Hook
是一種自然遵循
Hook
設計的約定,而并不是 React 的特性。
Hook
沒錯,就是函數和函數之間的邏輯複用,但是必須要遵循
Hook
的設計約定,不遵循的話,由于無法判斷某個函數是否包含對其内部
Hook
的調用,
React
将無法自動檢查你的
Hook
是否違反了
Hook
的規則。以下是本人封裝的以
Modal
的形式來
展示錯誤資訊
的
Hook
,僅供參考:
import React, { useState, useEffect } from 'react'
import { Modal, Table } from 'antd'
import { ColumnsType } from 'antd/es/table'
interface IData {
message: string
}
// 截取兩個字元串之間字元
function str_substr(start, end, str) {
// 擷取開始下标和結束下标
let firstIndex = str.indexOf(start)
let lastIndex = str.lastIndexOf(end)
return str.substring(firstIndex + 1, lastIndex)
}
const useErrModal = (data: string) => {
const [dataSource, setDataSource] = useState<Array<IData>>([])
const tableContainer = () => (
<Table size={'small'} dataSource={dataSource} columns={columns} pagination={false} />
)
const columns: ColumnsType<IData> = [
{
title: '錯誤明細',
dataIndex: 'message',
key: 'message'
}
]
// data 資料按照 [, ] 切割,資料事例 : "資料部分導入失敗:[第1行資料檢驗失敗原因:稅收編碼為必填項且必須為19位的有效編碼, 第2行資料檢驗失敗原因:稅率為必填項且為0開頭的小數且小數點後不能超過5位,稅收編碼為必填項且必須為19位的有效編碼]"
let splitStr = str_substr('[', ']', data)
let arr = splitStr.split(', ')
let list = []
arr.map((item, key) => {
list.push({
message: item
})
})
setDataSource(list)
Modal.warning({
title: '錯誤資訊彙總',
okText: '确定',
content: tableContainer
})
}
export default useErrModal
參考資料
[1]ahooks: https://ahooks.js.org/zh-CN
[2]react-use: https://github.com/streamich/react-use
[3]hooks 詳解: https://www.jianshu.com/p/d600f749bb19
[4]hooks 官方文檔: https://react.docschina.org/docs/hooks-intro.html
寫在最後
:
公衆号
專注分享
前端開發愛好者
前端相關
web
、
技術文章
資源、熱點資訊等,如果喜歡我的分享,給 🐟🐟 點一個
視訊教程
👍 或者
贊
➕ 都是對我最大的支援。
關注
歡迎
長按圖檔加好友
,我會第一時間和你分享
前端行業趨勢
,
面試資源
,
學習途徑
等等。

關注公衆号後,在首頁:
- 回複
,擷取最新大廠面試資料。面試資料
- 回複
,擷取 React 最新實戰教程。React實戰
- 回複
,擷取 Vue 最新實戰教程。Vue實戰
- 更多教程資源應用盡有,歡迎
關注擷取