React中useCallback 的基本使用和原理小結(jié)
useCallback 是 React 的一個核心 Hook,用于?緩存函數(shù)定義?,避免組件重新渲染時重復(fù)創(chuàng)建函數(shù)實例。以下是其基本使用方法:
1. 基本語法
const memoizedCallback = useCallback(
() => {
// 函數(shù)邏輯 (例如更新狀態(tài)、調(diào)用API等)
doSomething(a, b);
},
[a, b] // 依賴項數(shù)組
);
- ?第一個參數(shù)?:需要緩存的函數(shù)。
- ?第二個參數(shù)?:依賴項數(shù)組(Dependency Array),當數(shù)組中的變量變化時,函數(shù)會重新創(chuàng)建。
2. 核心作用
- ?避免不必要的函數(shù)重建?:默認情況下,組件每次渲染都會創(chuàng)建新的函數(shù)實例,使用
useCallback后可復(fù)用函數(shù)。 - ?優(yōu)化子組件渲染?:當緩存的函數(shù)作為 props 傳遞給子組件(配合
React.memo)時,可避免子組件不必要的重渲染?。
3. 使用示例
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
// 緩存函數(shù):依賴項為空數(shù)組,函數(shù)只創(chuàng)建一次
const increment = useCallback(() => {
setCount(prev => prev + 1); // 使用函數(shù)式更新避免閉包問題
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+1</button>
</div>
);
}
- 依賴項
[]表示函數(shù)僅在組件初次渲染時創(chuàng)建。 - 使用
setCount(prev => prev + 1)替代setCount(count + 1)可避免閉包陷阱(函數(shù)捕獲過時狀態(tài))?。
4. 適用場景
useCallback,本質(zhì)上是用于緩存函數(shù)。
如果函數(shù),是以props的方式,傳遞給子組件,為了每次避免子組件的渲染,建議使用useCallback進行包裹。
但是每一次,使用useCallback,我們考慮的首要問題是,這樣真的優(yōu)化了組件的性能嗎?其實大多數(shù)場景,如果不是類似列表渲染的場景,這樣不一定會優(yōu)化了性能。
也就是,函數(shù)作為props傳遞給性能敏感的子組件的場景,才是使用useCallback的時候。
useCallback的原理解析
useCallback的主要目的是在依賴項不變的情況下,返回同一個函數(shù)引用,避免函數(shù)重復(fù)創(chuàng)建,從而優(yōu)化性能。useCallback它會在首次渲染時(或依賴項變化時)創(chuàng)建一個新的函數(shù),并將其緩存起來。在后續(xù)渲染中,如果依賴項沒有變化,則返回緩存的函數(shù);否則,就重新創(chuàng)建函數(shù)并更新緩存。- 簡易的偽代碼,可能如下所示
let lastDeps; // 上一次的依賴項
let lastCallback; // 上一次緩存的函數(shù)
function useCallback(callback, deps) {
if (lastDeps === undefined) {
// 第一次調(diào)用
lastDeps = deps;
lastCallback = callback;
return callback;
}
// 檢查依賴項是否變化
const hasChanged = deps.some((dep, index) => dep !== lastDeps[index]);
if (hasChanged) {
lastDeps = deps;
lastCallback = callback;
}
return lastCallback;
}
每次掉用useCallback,返回的函數(shù),取決于依賴項有沒有發(fā)生變化。
React內(nèi)部是咋樣的呢?
1、Fiber 節(jié)點存儲機制
React 在 Fiber 節(jié)點(組件實例對應(yīng)的數(shù)據(jù)結(jié)構(gòu))中維護一個 memorizedState 鏈表,專門存儲 Hooks 狀態(tài)。
function updateCallback(callback, deps) {
const hook = updateWorkInProgressHook(); // 獲取當前 Hook 節(jié)點
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState; // 讀取緩存的上次狀態(tài)
// 依賴項對比:使用淺比較(shallow equal)
if (prevState !== null && areHookInputsEqual(nextDeps, prevState[1])) {
return prevState[0]; // 返回緩存的函數(shù)
}
// 依賴變化:緩存新函數(shù)
hook.memoizedState = [callback, nextDeps];
return callback;
}
2、依賴項對比算法
源碼中的 areHookInputsEqual 對依賴數(shù)組進行淺比較(類似 Object.is):
function areHookInputsEqual(nextDeps, prevDeps) {
if (prevDeps === null) return false;
for (let i = 0; i < prevDeps.length; i++) {
if (!Object.is(nextDeps[i], prevDeps[i])) {
return false;
}
}
return true;
}
這種優(yōu)化避免了深度比較的性能損耗
到此這篇關(guān)于React中useCallback 的基本使用和原理小結(jié)的文章就介紹到這了,更多相關(guān)React useCallback使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 關(guān)于react中useCallback的用法
- react中關(guān)于useCallback的用法
- 詳解react中useCallback內(nèi)部是如何實現(xiàn)的
- React Hooks之使用useCallback和useMemo進行性能優(yōu)化方式
- React?useCallback使用方法詳解
- React中memo useCallback useMemo方法作用及使用場景
- 解析React中useMemo與useCallback的區(qū)別
- react組件memo useMemo useCallback使用區(qū)別示例
- React?中?memo?useMemo?useCallback?到底該怎么用
相關(guān)文章
Hello?React的組件化方式之React入門小案例演示
這篇文章主要介紹了Hello?React的組件化方式-React入門小案例,本文通過Hello?React的案例,?來體驗一下React開發(fā)模式,?以及jsx的語法,需要的朋友可以參考下2022-10-10
React-Native左右聯(lián)動List的示例代碼
本篇文章主要介紹了React-Native左右聯(lián)動List的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
React18中請求數(shù)據(jù)的官方姿勢適用其他框架
這篇文章主要為大家介紹了官方回答在React18中請求數(shù)據(jù)的正確姿勢詳解,同樣也適用其他框架,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07
React+Ant Design開發(fā)環(huán)境搭建的實現(xiàn)步驟
這篇文章主要介紹了React+Ant Design開發(fā)環(huán)境搭建的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

