如何快速入門VUE3.0:進入學習
Hooks 用於不編寫class 的情況下,使用state 以及其他React 特性。那麼Hooks 究竟是什麼,為什麼要使用Hooks,React 提供了哪些常用Hooks,以及如何自訂Hooks 呢,下文將為您一一揭曉。
Hooks 譯為鉤子,Hooks 就是在函數組件內,負責鉤進外部功能的函數。
React 提供了一些常用鉤子,React 也支援自訂鉤子,這些鉤子都是用於為函數引入外部功能。
當我們在元件中,需要引入外部功能時,就可以使用React 提供的鉤子,或自訂鉤子。
例如在元件內引入可管理state 的功能,就可以使用useState 函數,下文會詳細介紹useState 的用法。
使用Hooks 有2 大原因:
在Hooks 出現之前,React 必須借用高階元件、render props 等複雜的設計模式才能實現邏輯的複用,但高階元件會產生冗餘的元件節點,讓偵錯更加複雜。
Hooks 讓我們可以在無需修改元件結構的情況下復用狀態邏輯,下文會詳細介紹自訂Hooks 的用法。
在class 元件中,同一個業務邏輯的程式碼分散在元件的不同生命週期函數中,而Hooks 讓針對同一個業務邏輯的程式碼聚合在一塊,讓業務邏輯清晰地隔離開,讓程式碼更容易理解和維護。
useState 是允許你在React 函數元件中加入state 的Hook。
使用範例如下:
import React, { useState } from 'react'; function Example() { // 宣告一個叫"count" 的state 變數const [count, setCount] = useState(0); // ...
以上程式碼宣告了一個初始值為0 的state 變數count,透過呼叫setCount 來更新目前的count。
useEffect 可以讓你在函數元件中執行副作用操作。
副作用是指一段和目前執行結果無關的程式碼,常用的副作用操作如資料取得、設定訂閱、手動更改React 元件中的DOM。
useEffect 可以接收兩個參數,程式碼如下:
useEffect(callback, dependencies)
第一個參數是要執行的函數 callback,第二個參數是可選的依賴項陣列dependencies。
其中依賴項是可選的,如果不指定,那麼callback 就會在每次函數元件執行完後都執行;如果指定了,那麼只有依賴項中的值發生變化的時候,它才會執行。
使用範例如下:
function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; return () => { // 可用來做清除,相當於class 元件的componentWillUnmount } }, [count]); // 指定依賴項為count,在count 更新時執行該副作用// ...
以上程式碼透過useEffect 實作了當依賴項count 更新時,執行副作用函數,並透過傳回回呼函數清除上一次的執行結果。
另外,useEffect 提供了四種執行副作用的時機:
useCallback 定義的回呼函數只會在依賴項改變時重新宣告這個回呼函數,這樣就確保了元件不會建立重複的回呼函數。而接收這個回呼函數作為屬性的元件,也不會頻繁地需要重新渲染。
使用範例如下:
const memoizedCallback = useCallback(() => { doSomething(a, b) }, [a, b])
以上程式碼在依賴項a、b 改變時,才會重新宣告回呼函數。
useMemo 定義的創建函數只會在某個依賴項改變時才重新計算,有助於每次渲染時不會重複的高開銷的計算,而接收這個計算值作為屬性的組件,也不會頻繁地需要重新渲染。
使用範例如下:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])
以上程式碼在依賴項a、b 改變時,才會重新計算。
useRef 傳回一個ref 對象,這個ref 物件在組件的整個生命週期內持續存在。
他有2 個用處:
保存DOM 節點的引入使用範例如下:
function TextInputWithFocusButton() { const inputEl = useRef(null) const onButtonClick = () => { // `current` 指向已掛載到DOM 上的文字輸入元素inputEl.current.focus() } return ( <> > ) }
以上程式碼透過useRef 建立了ref 對象,保存了DOM 節點的引用,可以對ref.current 做DOM 操作。
在多次渲染之間共用資料範例如下:
import React, { useState, useCallback, useRef } from 'react' export default function Timer() { // 定義time state 用來保存計時的累積時間const [time, setTime] = useState(0) // 定義timer 這樣一個容器用於在跨元件渲染之間保存一個變數const timer = useRef(null) // 開始計時的事件處理函數const handleStart = useCallback(() => { // 使用current 屬性設定ref 的值timer.current = window.setInterval(() => { setTime((time) => time + 1) }, 100) }, []) // 暫停計時的事件處理函數const handlePause = useCallback(() => { // 使用clearInterval 來停止計時window.clearInterval(timer.current) timer.current = null }, []) return ({time / 10} seconds.) }
以上程式碼透過useRef 創建了一個變數名為timer 的ref 對象,該對象可以在跨組件渲染時調用,在開始計時時新建計時器,並在暫停計時時清空計時器。
useContext 用於接收一個context 物件並傳回該context 的值,可以實現跨層級的資料共用。
範例如下:
// 建立一個context 物件const MyContext = React.createContext(initialValue) function App() { return ( // 透過Context.Provider 傳遞context 的值) } function Container() { return } function Test() { // 取得Context 的值const theme = useContext(MyContext) // 1 return }
以上程式碼透過useContext 取得了App 元件中定義的Context,做到了跨層次組件的資料共享。
useReducer 用來引入Reducer 功能。
範例如下:
const [state, dispatch] = useReducer(reducer, initialState)
它接受Reducer 函數和狀態的初始值作為參數,並傳回一個陣列。陣列的第一個成員是狀態的目前值,第二個成員是傳送action 的dispatch 函數。
透過自訂Hooks,可以將元件邏輯提取到可重複使用的函數中。
自訂Hooks 是函數,它有2 個特徵區分於普通函數:
範例如下:
import { useState, useCallback } from 'react' function useCounter() { // 定義count 這個state 用來保存目前數值const [count, setCount] = useState(0) // 實作加1 的操作const increment = useCallback(() => setCount(count + 1), [count]) // 實作減1 的操作const decrement = useCallback(() => setCount(count - 1), [count]) // 重置計數器const reset = useCallback(() => setCount(0), []) // 將業務邏輯的操作export 出去供呼叫者使用return { count, increment, decrement, reset } } // 元件1 function MyComponent1() { const { count, increment, decrement, reset } = useCounter() } // 元件2 function MyComponent2() { const { count, increment, decrement, reset } = useCounter() }
以上程式碼透過自訂Hooks useCounter,輕鬆的在MyComponent1 元件和MyComponent2 元件之間重複使用業務邏輯。
React 官方提供了react-use 函式庫,其中封裝了大量可直接使用的自訂Hooks,幫助我們簡化元件內部邏輯,提高程式碼可讀性、可維護性。
其中我們常用的自訂Hooks 有:
可至react-use 官網學習使用。
本文從Hooks 究竟是什麼,為什麼要使用Hooks,React 提供了哪些常用Hooks,以及如何自訂Hooks 4 個面向介紹了React Hooks,相信大家對React Hooks 已經有了更深入的理解。
希望能對你有幫助,感謝閱讀~