第五節:React Hooks進階篇-如何用useMemo/useCallback優化性能

  • 反模式:濫用導致的內存開銷
  • React 19編譯器自動Memoization原理

React Hooks 性能優化進階:從手動到自動 Memoization

(基于 React 18 及以下版本,結合 React 19 新特性分析)


一、useMemo/useCallback 的正確使用場景與優化策略

1. useMemo:緩存高開銷計算結果

核心作用:避免每次渲染重復執行復雜計算(如數據過濾、數學運算)。
正確用法

const filteredList = useMemo(() => bigDataList.filter(item => item.category === activeCategory), [bigDataList, activeCategory] // 僅依賴變化時重新計算
);

適用場景
? 數據量大的列表過濾/排序
? 復雜對象/數組的派生狀態(如用戶權限樹、圖表數據預處理)
? 需穩定引用的對象(避免子組件因引用變化重新渲染)

2. useCallback:穩定函數引用

核心作用:避免函數因引用變化導致子組件無效渲染。
正確用法

const handleSubmit = useCallback((values) => api.postForm(values), [] // 空依賴:函數邏輯不依賴外部變量
);

適用場景
? 事件處理函數傳遞給 React.memo 優化的子組件
? 依賴閉包值的異步操作(如定時器、防抖函數)


二、反模式:濫用導致的性能陷阱

1. 過度緩存導致內存開銷

? 問題:對簡單計算或頻繁變化的值使用 useMemo,反而增加內存和比較成本
? 示例

// ? 錯誤:簡單計算無需緩存
const total = useMemo(() => a + b, [a, b]); 
2. 依賴項管理不當

? 缺失依賴:導致閉包中引用過期值

const [count, setCount] = useState(0);
const increment = useCallback(() => {setCount(count + 1); // ? 依賴缺失,始終基于初始count
}, []); 

? 冗余依賴

const fetchData = useCallback(() => {getData(userId); 
}, [userId, getData]); // ? getData若為穩定引用(如來自useCallback),則無需重復依賴
3. 忽略組件拆分優化

? 問題:依賴 useMemo 緩存大型組件渲染結果,而非拆分細粒度組件
? 優化方案

// ? 拆分子組件并用 React.memo 優化
const ExpensiveSection = memo(({ data }) => <div>{data}</div>);

三、React 19 編譯器自動 Memoization 原理與影響

1. 自動優化的核心機制

? 智能依賴追蹤:編譯器靜態分析組件代碼,自動識別變量間的依賴關系
? 函數穩定性保證:即使父組件重新渲染,若函數邏輯未變化,編譯器自動保持引用穩定
? 計算緩存:自動對高開銷操作(如數組遍歷、復雜運算)實施類似 useMemo 的優化

2. 開發者行為變化

? 代碼簡化:不再需要手動添加 useMemo/useCallback

// React 19 ? 自動優化
const filteredList = bigData.filter(item => item.category === activeCategory);

? 例外場景
? 第三方庫依賴嚴格引用相等性(如某些動畫庫)
? 超高頻更新場景(如實時游戲引擎)需手動干預

3. 性能優化優先級調整

? 優先策略

  1. 保持代碼簡潔,依賴編譯器自動優化
  2. 使用性能分析工具定位真實瓶頸(如 React DevTools)
  3. 僅在必要時手動添加 Memoization

四、新舊版本性能優化對比

優化維度React 18(手動)React 19(自動)
代碼復雜度高(需顯式聲明依賴和緩存)低(編譯器自動處理)
內存占用可能因過度緩存增加按需優化,減少冗余緩存
維護成本高(需持續監控依賴關系)低(聚焦業務邏輯)
適用場景所有場景除極端性能敏感場景外全覆蓋

五、最佳實踐總結

  1. React 18 及以下版本
    ? 對高頻計算/函數傳遞場景精準使用 useMemo/useCallback
    ? 通過 memo + useCallback 避免深層子組件無效渲染
  2. React 19 及以上版本
    ? 優先編寫直觀代碼,信任編譯器優化能力
    ? 升級后逐步移除冗余 Memoization 代碼
  3. 通用原則
    ? 避免過早優化,先用工具驗證性能瓶頸
    ? 保持組件細粒度化,減少單組件渲染壓力

通過合理運用手動優化與編譯器自動能力,可顯著提升應用性能與代碼可維護性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76487.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76487.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76487.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

windows server C# IIS部署

1、添加IIS功能 windows server 2012、windows server 2016、windows server 2019 說明&#xff1a;自帶的是.net 4.5 不需要安裝.net 3.5 盡量使用 windows server 2019、2016高版本&#xff0c;低版本會出現需要打補丁的問題 2、打開IIS 3、打開iis應用池 .net 4.5 4、添…

Elasticsearch的Java客戶端庫QueryBuilders查詢方法大全

matchAllQuery 使用方法&#xff1a;創建一個查詢&#xff0c;匹配所有文檔。 示例&#xff1a;QueryBuilders.matchAllQuery() 注意事項&#xff1a;這種查詢不加任何條件&#xff0c;會返回索引中的所有文檔&#xff0c;可能會影響性能&#xff0c;特別是文檔數量很多時。 ma…

C#進階學習(六)單向鏈表和雙向鏈表,循環鏈表(下)循環鏈表

目錄 &#x1f4ca; 鏈表三劍客&#xff1a;特性全景對比表 一、循環鏈表節點類 二、循環鏈表的整體設計框架 三、循環列表中的重要方法&#xff1a; &#xff08;1&#xff09;頭插法&#xff0c;在頭結點前面插入新的節點 &#xff08;2&#xff09;尾插法實現插入元素…

交換網絡基礎

學習目標 掌握交換機的基本工作原理 掌握交換機的基本配置 交換機的基本工作原理 交換機是局域網&#xff08;LAN&#xff09;中實現數據高效轉發的核心設備&#xff0c;工作在 數據鏈路層&#xff08;OSI 模型第二層&#xff09;&#xff0c;其基本工作原理可概括為 “學習…

科學研究:怎么做

科研&#xff08;科學研究&#xff09;?? 是指通過系統化的方法&#xff0c;探索自然、社會或人文領域的未知問題&#xff0c;以發現新知識、驗證理論或解決實際問題的活動。它的核心是??基于證據的探索與創新??&#xff0c;旨在推動人類認知和技術的進步。 科研的核心要…

算法題(128):費解的開關

審題&#xff1a; 本題需要我們將多組測試用例中拉燈數小于等于6的最小拉燈數輸出&#xff0c;若拉燈數最小值仍大于6&#xff0c;則輸出-1 思路&#xff1a; 方法一&#xff1a;二進制枚舉 首先我們先分析一下基本特性&#xff1a; 1.所有的燈不可能重復拉&#xff1a;若拉的數…

MFC文件-屏幕錄像

下載本文件 本文件將獲取屏幕圖像數據的所有代碼整合到兩個文件中&#xff08;ScreenRecorder.h和ScreenRecorder.cpp&#xff09;&#xff0c;使獲取屏幕圖像數據變得簡單。輸出IYUV視頻流。還可以獲取系統播放的聲音&#xff0c;輸出PCM音頻流。由于使用了MFC類&#xff0c;本…

0801ajax_mock-網絡ajax請求1-react-仿低代碼平臺項目

0 vite配置proxy代理 vite.config.ts代碼如下圖所示&#xff1a; import { defineConfig } from "vite"; import react from "vitejs/plugin-react";// https://vite.dev/config/ export default defineConfig({plugins: [react()],server: {proxy: {&qu…

JVM筆記【一】java和Tomcat類加載機制

JVM筆記一java和Tomcat類加載機制 java和Tomcat類加載機制 Java類加載 * loadClass加載步驟類加載機制類加載器初始化過程雙親委派機制全盤負責委托機制類關系圖自定義類加載器打破雙親委派機制 Tomcat類加載器 * 為了解決以上問題&#xff0c;tomcat是如何實現類加載機制的…

IP編址(來自YESLAB新網工的筆記)

上層協議類型 概念&#xff1a;通常指的是位于網絡層&#xff08;如 IP 層&#xff09;以上的協議類型&#xff0c;這些協議在數據傳輸時需要由網絡層&#xff08;或更低層&#xff09;協議承載。以 IP 協議為例&#xff0c;IP 報文頭部中的 協議字段&#xff08;Protocol Fie…

SpringBoot學習(過濾器Filter。攔截器Interceptor。全局異常捕獲處理器GlobalExceptionHandler)(詳細使用教程)

目錄 一、過濾器Filter。 1.1定義與規范。 1.2工作原理與范圍。 1.3使用場景。 1.4 SpringBoot實現過濾器。&#xff08;Filter配置2種方式&#xff09; <1>注解配置(WebFilter、Order、ServletComponentScan)。 創建過濾器類。 啟用 Servlet 組件掃描。 <2>配置類…

c++題目_P1443 馬的遍歷

P1443 馬的遍歷 # P1443 馬的遍歷 ## 題目描述 有一個 $n \times m$ 的棋盤&#xff0c;在某個點 $(x, y)$ 上有一個馬&#xff0c;要求你計算出馬到達棋盤上任意一個點最少要走幾步。 ## 輸入格式 輸入只有一行四個整數&#xff0c;分別為 $n, m, x, y$。 ## 輸出格式 …

清華《數據挖掘算法與應用》K-means聚類算法

使用k均值聚類算法對表4.1中的數據進行聚類。代碼參考P281。 創建一個名為 testSet.txt 的文本文件&#xff0c;將以下內容復制粘貼進去保存即可&#xff1a; 0 0 1 2 3 1 8 8 9 10 10 7 表4.1 # -*- coding: utf-8 -*- """ Created on Thu Apr 17 16:59:58 …

HarmonyOS-ArkUI V2工具類:AppStorageV2:應用全局UI狀態存儲

AppStorageV2是一個能夠跨界面存儲數據,管理數據的類。開發者可以使用AppStorageV2來存儲全局UI狀態變量數據。它提供的是應用級的全局共享能力,開發者可以通過connect綁定同一個key,進行跨ability數據共享。 概述 AppStorageV2是一個單例,創建時間是應用UI啟動時。其目的…

打靶日記 zico2: 1

一、探測靶機IP&#xff08;進行信息收集&#xff09; 主機發現 arp-scan -lnmap -sS -sV -T5 -p- 192.168.10.20 -A二、進行目錄枚舉 發現dbadmin目錄下有個test_db.php 進入后發現是一個登錄界面&#xff0c;嘗試弱口令&#xff0c;結果是admin&#xff0c;一試就出 得到加…

使用Java基于Geotools的SLD文件編程式創建與磁盤生成實戰

前言 在地理信息系統&#xff08;GIS&#xff09;領域&#xff0c;地圖的可視化呈現至關重要&#xff0c;而樣式定義語言&#xff08;SLD&#xff09;文件為地圖元素的樣式配置提供了強大的支持。SLD 能夠精確地定義地圖圖層中各類要素&#xff08;如點、線、面、文本等&#x…

kubernetes》》k8s》》Service

Kubernetes 中的 Service 是用于暴露應用服務的核心抽象&#xff0c;為 Pod 提供穩定的訪問入口、負載均衡和服務發現機制。Service在Kubernetes中代表了一組Pod的邏輯集合&#xff0c;通過創建一個Service&#xff0c;可以為一組具有相同功能的容器應用提供一個統一的入口地址…

【HDFS】EC重構過程中的校驗功能:DecodingValidator

一、動機 DecodingValidator是在HDFS-15759中引入的一個用于校驗EC數據重構正確性的組件。 先說下引入DecodingValidator的動機,據很多已知的ISSUE(如HDFS-14768, HDFS-15186, HDFS-15240,這些目前都已經fix了)反饋, EC在重構的時候可能會有各種各樣的問題,導致數據錯誤…

現代c++獲取linux系統架構

現代c獲取linux系統架構 前言一、使用命令獲取系統架構二、使用c代碼獲取系統架構三、驗證四、總結 前言 本文介紹一種使用c獲取linux系統架構的方法。 一、使用命令獲取系統架構 linux系統中可以使用arch或者uname -m命令來獲取當前系統架構&#xff0c;如下圖所示 archuna…

didFinishLaunching 與「主線程首次 idle」, 哪個是更優的啟動結束時間點 ?

結論先行 在這兩個候選時間點里—— application:didFinishLaunchingWithOptions: 執行結束主線程第一次進入 idle&#xff08;RunLoop kCFRunLoopBeforeWaiting&#xff09; 若你只能二選一&#xff0c;以「主線程首次 idle」作為 啟動結束 更合理。它比 didFinishLaunchin…