Hooks 用於在不編寫 class 的情況下,使用 state 以及其他 React 特性。那麼 Hooks 究竟是什麼,為什麼要使用 Hooks,React 提供了哪些常用 Hooks,以及如何自定義 Hooks 呢,下文將為您一一揭曉。【相關推薦:Redis視訊教學】
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 ( <> <input ref={inputEl} type='text' /> <button onClick={onButtonClick}>Focus the input</button> </> ) }
以上程式碼通過 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 ( <div> {time / 10} seconds. <br /> <button onClick={handleStart}>Start</button> <button onClick={handlePause}>Pause</button> </div> ) }
以上程式碼通過 useRef 建立了一個變數名為 timer 的 ref 物件,該物件可以在跨元件渲染時呼叫,在開始計時時新建計時器,在暫停計時時清空計時器。
useContext 用於接收一個 context 物件並返回該 context 的值,可以實現跨層級的資料共用。
範例如下:
// 建立一個 context 物件 const MyContext = React.createContext(initialValue) function App() { return ( // 通過 Context.Provider 傳遞 context 的值 <MyContext.Provider value='1'> <Container /> </MyContext.Provider> ) } function Container() { return <Test /> } function Test() { // 獲取 Context 的值 const theme = useContext(MyContext) // 1 return <div></div> }
以上程式碼通過 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 已經有了更加深入的理解。
希望能對你有所幫助,感謝閱讀~
更多程式設計相關知識,請存取:!!
以上就是一文帶你深入瞭解React Hooks!的詳細內容,更多請關注TW511.COM其它相關文章!