
- ReactJS 教程
- ReactJS - 首頁
- ReactJS - 簡介
- ReactJS - 路線圖
- ReactJS - 安裝
- ReactJS - 特性
- ReactJS - 優點與缺點
- ReactJS - 架構
- ReactJS - 建立 React 應用
- ReactJS - JSX
- ReactJS - 元件
- ReactJS - 巢狀元件
- ReactJS - 使用新建立的元件
- ReactJS - 元件集合
- ReactJS - 樣式
- ReactJS - 屬性 (props)
- ReactJS - 使用屬性建立元件
- ReactJS - props 驗證
- ReactJS - 建構函式
- ReactJS - 元件生命週期
- ReactJS - 事件管理
- ReactJS - 建立一個事件感知元件
- ReactJS - 在 Expense Manager 應用中引入事件
- ReactJS - 狀態管理
- ReactJS - 狀態管理 API
- ReactJS - 無狀態元件
- ReactJS - 使用 React Hooks 進行狀態管理
- ReactJS - 使用 React Hooks 的元件生命週期
- ReactJS - 佈局元件
- ReactJS - 分頁
- ReactJS - Material UI
- ReactJS - Http 客戶端程式設計
- ReactJS - 表單程式設計
- ReactJS - 受控元件
- ReactJS - 非受控元件
- ReactJS - Formik
- ReactJS - 條件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 動畫
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - 表格
- ReactJS - 使用 Flux 管理狀態
- ReactJS - 測試
- ReactJS - CLI 命令
- ReactJS - 構建和部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 簡介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定義 Hooks
- ReactJS 高階
- ReactJS - 可訪問性
- ReactJS - 程式碼分割
- ReactJS - Context
- ReactJS - 錯誤邊界
- ReactJS - 轉發 Refs
- ReactJS - Fragments
- ReactJS - 高階元件
- ReactJS - 與其他庫整合
- ReactJS - 效能最佳化
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - 無 ES6 ECMAScript 的 React
- ReactJS - 無 JSX 的 React
- ReactJS - Reconciliation
- ReactJS - Refs 和 DOM
- ReactJS - Render Props
- ReactJS - 靜態型別檢查
- ReactJS - Strict Mode
- ReactJS - Web Components
- 附加概念
- ReactJS - 日期選擇器
- ReactJS - Helmet
- ReactJS - 內聯樣式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 走馬燈
- ReactJS - 圖示
- ReactJS - 表單元件
- ReactJS - 參考 API
- ReactJS 有用資源
- ReactJS - 快速指南
- ReactJS - 有用資源
- ReactJS - 討論
ReactJS - useCallback
useCallback hook 類似於 useMemo hook,它提供記憶函式而非值的功能。由於回撥函式是 JavaScript 程式設計中不可或缺的一部分,並且回撥函式是透過引用傳遞的,因此 React 提供了一個單獨的 hook,useCallback 來記憶回撥函式。理論上,useMemo hook 本身可以實現 useCallback 的功能。但是,useCallback 提高了 React 程式碼的可讀性。
useCallback hook 的簽名
useCallback hook 的簽名如下:
const <memoized_callback_fn> = useCallback(<callback_fn>, <dependency_array>);
這裡,useCallback 接受兩個輸入並返回一個記憶的回撥函式。輸入引數如下:
callback_fn - 要記憶的回撥函式。
dependency_array - 包含回撥函式所依賴的變數。
useCallback hook 的輸出是 callback_fn 的記憶回撥函式。useCallback hook 的使用方法如下:
const memoizedCallbackFn = useCallback(() => { // code }, [a, b])
注意 - useCallback(callback_fn, dependency_array) 等效於 useMemo(() => callback_fn, dependency_array)。
應用 useCallback
讓我們學習如何透過建立一個 React 應用來應用 useCallback hook。
首先,使用 create-react-app 命令建立一個並啟動一個 React 應用,如下所示:
create-react-app myapp cd myapp npm start
接下來,在 components 資料夾下建立一個元件 PureListComponent (src/components/PureListComponent.js)
import React from "react"; function PureListComponent() { return <div>List</div> } export default PureListComponent
接下來,使用 PureListComponent 元件更新根元件,如下所示:
import PureListComponent from './components/PureListComponent'; function App() { return ( <div style={{ padding: "5px" }}> <PureListComponent /> </div> ); } export default App;
接下來,開啟 PureListComponent.js 並新增兩個 props
要在元件中顯示的專案列表
用於在控制檯中顯示使用者點選的專案的回撥函式
import React from "react"; function PureListComponent(props) { const items = props['items']; const handleClick = props['handleClick'] console.log("I am inside the PureListComponent") return ( <div> {items.map((item, idx) => <span key={idx} onClick={handleClick}>{item} </span> )} </div> ) } export default React.memo(PureListComponent)
這裡我們有:
使用 items props 獲取專案列表
使用 handleClick 獲取點選事件的處理程式
使用 React.memo 包裝元件以記憶元件。由於元件將為給定的輸入集渲染相同的輸出,因此它在 React 中被稱為 PureComponent。
接下來,讓我們更新 App.js 並使用 PureListComponent,如下所示:
import React, {useState, useEffect} from 'react'; import PureListComponent from './components/PureListComponent'; function App() { // array of numbers var listOfNumbers = [...Array(100).keys()]; // callback function const handleCallbackFn = (e) => { console.log(e.target.innerText) } const [currentTime, setCurrentTime] = useState(new Date()) useEffect(() => { let interval = setInterval(() => { setCurrentTime(new Date()) }, 1000) return () => clearInterval(interval) }, [currentTime]) return ( <div style={ { padding: "5px" } }> <PureListComponent items={listOfNumbers} handleClick={handleCallbackFn}/> <div>Time: <b>{currentTime.toLocaleString().split(',')[1]}</b></div> </div> ); } export default App;
這裡我們包含了一個狀態 currentTime,並使用 setInterval 每秒更新它,以確保元件每秒重新渲染。
我們可能認為 PureListComponent 不會每秒重新渲染,因為它使用了 React.memo。但是,它會重新渲染,因為 props 值是引用型別。
接下來,更新根元件並使用 useMemo 和 useCallback 來保留陣列和回撥函式,如下所示:
import React, {useState, useEffect, useCallback, useMemo} from 'react'; import PureListComponent from './components/PureListComponent'; function App() { // array of numbers const listOfNumbers = useMemo(() => [...Array(100).keys()], []); // callback function const handleCallbackFn = useCallback((e) => console.log(e.target.innerText), []) const [currentTime, setCurrentTime] = useState(new Date()) useEffect(() => { let interval = setInterval(() => { setCurrentTime(new Date()) }, 1000) return () => clearInterval(interval) }, [currentTime]) return ( <div style={ { padding: "5px" } }> <PureListComponent items={listOfNumbers} handleClick={handleCallbackFn}/> <div>Time: <b>{currentTime.toLocaleString().split(',')[1]}</b></div> </div> ); } export default App;
這裡我們有:
使用 useMemo 保留 items 陣列
使用 useCallback 保留 handleClick 回撥函式
最後,在瀏覽器中檢查應用程式,它將不會每秒重新渲染 PureListComponent。

useCallback 的用例
useCallback hook 的一些用例如下:
具有函式 props 的純函式元件
useEffect 或其他具有函式作為依賴項的 hooks
在去抖動/節流或類似操作期間使用函式
優點
useCallback hook 的優點如下:
易於使用的 API
易於理解
提高應用程式的效能
缺點
從技術上講,useCallback 沒有缺點。但是,在應用程式中過度使用 useCallback 會帶來以下缺點。
降低應用程式的可讀性
降低應用程式的可理解性
除錯應用程式很複雜
開發人員應該深入瞭解 JavaScript 語言才能使用它
總結
useCallback 易於使用並提高效能。同時,useCallback 應該只在絕對必要時使用。它不應該在每種情況下都使用。一般規則是檢查應用程式的效能。如果需要改進,那麼我們可以檢查使用 useCallback 是否有助於提高效能。如果我們得到肯定的回應,那麼我們可以使用它。否則,我們可以將其留給 React 來改進和最佳化應用程式的效能。