前端開發 React 狀態優化

為了更深入地理解 React 狀態管理的性能問題及其解決方案,本文將詳細分析 React Context 和 State 的性能問題,配以示例代碼說明優化策略。之后,討論 Redux 作為不可變庫的性能問題,并引出 Immer 作為優化解決方案。

1.?React State 和 Context 的性能問題

1.1.?React State 性能問題

React State 是組件內部管理數據的核心。當狀態發生變化時,會觸發組件的重新渲染,這可能引發性能問題。

常見的性能問題:

  • 頻繁更新:頻繁更新會導致組件不斷重新渲染,影響用戶體驗。

  • 深層次嵌套對象:復雜的嵌套對象或數組更新時,會增加渲染的成本。

  • 狀態與組件耦合:狀態過多集中在某個組件上,容易引發多次不必要的渲染。

優化方案及代碼示例:

1.?減少狀態范圍:將狀態控制在必要的范圍內。

// 不好的例子:狀態集中在父組件
function Parent() {const [count, setCount] = useState(0);return (<div><Child1 count={count} /><Child2 setCount={setCount} /></div>);
}// 改進方案:狀態局部化,減少不必要的渲染
function Child1() {const [count, setCount] = useState(0);return <button onClick={() => setCount(count + 1)}>Increment {count}</button>;
}

2. 使用 useMemo 和 useCallback:避免在組件渲染時重復創建對象和函數。

// 使用 useMemo 緩存計算結果
const expensiveValue = useMemo(() => calculateExpensiveValue(count), [count]);// 使用 useCallback 緩存函數
const handleClick = useCallback((prev) => setCount((prev) => prev + 1), []);

3.?使用不可變數據更新狀態。

// 不可變數據更新
const updateArray = (index, newValue) => {setArray((prev) => prev.map((item, i) => (i === index ? newValue : item)));
};

1.2.?React Context 性能問題

React Context 用于在組件樹中共享數據,避免了逐層傳遞 props,但 Context 的更新可能導致整個訂閱樹的重渲染。

常見的性能問題:

  • 頻繁更新:每次 Context 更新都會引發所有訂閱組件的重渲染。

  • 單一大 Context:將所有狀態放在一個 Context 中,會導致頻繁更新,影響性能。

優化方案及代碼示例:

1.?分離 Context,減少影響范圍。

// 將 Context 分離為多個小 Context
const UserContext = createContext();
const ThemeContext = createContext();function App() {return (<UserContext.Provider value={user}><ThemeContext.Provider value={theme}><Component /></ThemeContext.Provider></UserContext.Provider>);
}

2.?使用 React.memo 優化訂閱組件。

// 使用 React.memo 避免不必要的重渲染
const UserComponent = React.memo(function UserComponent({ user }) {console.log("UserComponent rendered");return <div>User: {user.name}</div>;
});

3.?選擇性訂閱:useContextSelector?。

// 使用 useContextSelector 選擇性訂閱 Context 的部分狀態
import { useContextSelector } from 'use-context-selector';const username = useContextSelector(UserContext, (state) => state.name);

2.?Redux 和不可變數據的性能問題

2.1.?Redux 的性能問題

Redux 使用不可變數據管理應用狀態,這使得狀態變化更可預測,但也帶來了性能問題。

常見的性能問題:

  • 深拷貝的開銷:復雜狀態對象的深拷貝會消耗大量性能。

  • 手動實現不可變邏輯:編寫 reducer 時,手動處理不可變邏輯容易出錯且代碼復雜。

  • 不必要的重新渲染:Redux Store 更新時,所有訂閱組件都會檢查更新,可能會導致不必要的渲染。

  • useSelector 精準訂閱狀態。

問題示例:

// 手動實現不可變更新邏輯,復雜且易出錯
function reducer(state, action) {switch (action.type) {case 'UPDATE_ITEM':return {...state,items: state.items.map((item) =>item.id === action.payload.id ? {...item, value: action.payload.value } : item),};default:return state;}
}

2.2.?引入 Immer 作為解決方案

Immer 是一個不可變數據管理庫,它允許你用可變風格編寫代碼,但內部會保持不可變性。Immer 使用代理機制捕獲對草稿狀態的更改,并生成新的不可變狀態。

2.2.1.?Immer 的優勢

  • 簡化代碼:可以使用普通的可變寫法,避免手動深拷貝。

  • 性能優化:只在需要的地方進行深拷貝,減少不必要的開銷。

  • 更安全的狀態管理:自動確保狀態不可變性。

2.2.2.?Immer 使用示例

import { produce } from 'immer';// 使用 Immer 編寫 reducer
const reducer = (state = initialState, action) =>produce(state, (draft) => {switch (action.type) {case 'ADD_TODO':draft.todos.push({ id: Date.now(), text: action.payload });break;case 'TOGGLE_TODO':const todo = draft.todos.find((todo) => todo.id === action.payload);if (todo) todo.completed = !todo.completed;break;default:break;}});// 組件中使用 Immer
const [state, dispatch] = useReducer(reducer, { todos: [] });const addTodo = (text) => dispatch({ type: 'ADD_TODO', payload: text });
const toggleTodo = (id) => dispatch({ type: 'TOGGLE_TODO', payload: id });

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

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

相關文章

劍指offer第2版:雙指針+排序+分治+滑動窗口

一、p129-JZ21使奇數位于偶數前面&#xff08;不考慮相對位置&#xff09;&#xff08;hoare快排雙指針&#xff09; 調整數組順序使奇數位于偶數前面(二)_牛客題霸_牛客網 如果不考慮相對位置的話&#xff0c;那么我們可以模仿hoare快排&#xff0c;使用雙指針的思想&#xf…

14-C語言:第14天筆記

C語言&#xff1a;第14天筆記 內容提要 指針 變量指針與指針變量 指針變量做函數參數指針變量指向數組元素 數組指針與指針數組 數組指針回顧 變量指針與指針變量 變量指針&#xff1a;變量的地址值&#xff08;首地址&#xff09;&#xff0c;本質是指針、地址 指針變量&#…

【筆記】活度系數推導

文章目錄一、理想溶液的假設與局限性1.1 理想溶液的定義1.2 理想溶液的局限性二、活度與活度系數的引入2.1 活度的定義2.2 修正后的化學勢表達式三、活度系數的物理意義四、為什么需要活度系數&#xff1f;4.1 理論需求4.2 擴散理論中的必要性五、活度系數的具體作用5.1 在化學…

基于Docker的GPU版本飛槳PaddleOCR部署深度指南(國內鏡像)2025年7月底測試好用:從理論到實踐的完整技術方案

還是網上沒找到這個基于Docker的GPU版本飛槳PaddleOCR部署教程&#xff0c;于是就有了這一篇。 這個的確坑很多&#xff0c;可能后面變一個版本就不好用了&#xff0c;也是為什么這篇博客不完全粘貼代碼的原因。 端口是示例&#xff0c;可以隨意改。在人工智能與文檔數字化高速…

Python-初學openCV——圖像預處理(三)

目錄 一、邊緣填充 1、邊界復制 2、邊界反射 3、邊界反射101 4、邊界常數 5、邊界包裹 二、透視變換 三、圖像掩膜 1、制作掩膜 2、與運算 3、顏色替換 四、ROI切割 五、圖像添加水印 一、邊緣填充 我們對圖像進行處理后&#xff0c;需要對空出來的區域進行一個填充…

【ESP32設備通信】-W5500與ESP32 /ESP32 S3集成

W5500與ESP32 /ESP32 S3集成 文章目錄 W5500與ESP32 /ESP32 S3集成 1、W5500介紹 2、硬件準備與接線 3、代碼實現 3.1 以太網設置 3.2 簡單HTTP請求 3.3 HTTPS請求 3.4 查詢證書 ESP32 憑借其強大的 Wi-Fi 功能,一直是物聯網項目的熱門選擇。ESP32 現在支持帶有 SSL 的原生以太…

vue - 使用canvas繪制驗證碼

封裝繪制驗證碼 verify-code.vue<template><div class"captcha"><canvas ref"canvasRef" :width"width" :height"height" click"refreshCaptcha"></canvas></div> </template><scri…

[10月考試] F

[10月考試] F 題目描述 給定長度為 nnn 的序列 ana_nan?&#xff0c;保證 aia_iai? 為非負整數。 mmm 次詢問&#xff0c;每次給定區間 l,rl,rl,r&#xff0c;求出 al,al1,…,ara_l,a_{l1},\ldots,a_ral?,al1?,…,ar? 的 mexmexmex。 對于一個序列&#xff0c;定義其 mexm…

收集了全球55個AI寫作工具

我們即將推出一整套AI生產力工具矩陣&#xff0c;覆蓋內容創作&#xff08;AI寫作助手&#xff09;、視覺設計&#xff08;智能圖像處理&#xff09;、音視頻制作&#xff08;自動轉錄與編輯&#xff09;及智能編程等多個核心領域。這些解決方案通過先進的機器學習算法&#xf…

Elastic 勞動力的生成式 AI:ElasticGPT 的幕后解析

作者&#xff1a;來自 Elastic Jay Shah, Adhish Thite ElasticGPT — 由 Elastic 提供支持&#xff0c;專為 Elastic 打造 ElasticGPT 是我們基于檢索增強生成&#xff08;RAG&#xff09;框架構建的內部生成式 AI &#xff08;GenAI&#xff09;助手。它是使用 Elastic 自有…

CS231n-2017 Assignment1

KNN&#xff1a;這里要求我們完成一個KNN分類器&#xff0c;實現對圖片使用KNN算法進行分類標簽k_nearest_neighbor.py這里要求我們完成4個接口# X:測試集 # 使用兩個循環 def compute_distances_two_loops(self, X):num_test X.shape[0]num_train self.X_train.shape[0]dist…

[python][flask]Flask-Principal 使用詳解

Flask-Principal 是一個專為 Flask 應用設計的身份管理和權限控制擴展。它能夠幫助開發者輕松實現用戶身份驗證和權限管理&#xff0c;從而提升應用的安全性和用戶體驗。該項目最初由 Ali Afshar 開發&#xff0c;現已成為 Pallets 社區生態系統的一部分&#xff0c;由社區共同…

抖音與B站爬蟲實戰,獲取核心數據

本文將深入講解兩大主流短視頻平臺&#xff08;抖音、B站&#xff09;的爬蟲實戰技術&#xff0c;提供可直接運行的代碼解決方案&#xff0c;并分享突破反爬機制的核心技巧。一、平臺特性與爬蟲難點對比平臺數據價值主要反爬措施推薦抓取方式抖音視頻數據、用戶畫像、熱榜簽名驗…

WSL切換網絡模式

WSL切換網絡模式問題WSL從NAT改成MIRRORED找到WSL Setting修改配置重啟電腦&#xff08;注意不是重啟WSL&#xff09;運行pio run驗證IP問題 從魚香ROS買了一個小魚車&#xff0c;開始學習&#xff0c;然而裝環境都要搞死我了。 垃圾VirtualBox我新買的電腦&#xff0c;裝個Vi…

[Linux入門] Linux 遠程訪問及控制全解析:從入門到實戰

目錄 一、SSH 遠程管理&#xff1a;為什么它是遠程訪問的首選&#xff1f; 1??什么是 SSH&#xff1f; 2??SSH 為什么比傳統工具更安全&#xff1f; 3??SSH 的 “三大組成部分” 4??SSH 工作的 “五步流程” 5??常用 SSH 工具 二、實戰&#xff1a;構建 SSH 遠…

n8n AI資訊聚合與分發自動化教程:從數據獲取到微信與Notion集成

引言 n8n簡介&#xff1a;自動化工作流利器 n8n是一款功能強大的開源自動化工具&#xff0c;采用獨特的“公平代碼”&#xff08;Fair-Code&#xff09;許可模式&#xff0c;旨在幫助用戶連接各種應用程序和服務&#xff0c;從而實現工作流的自動化。它通過直觀的可視化界面&am…

遞歸查詢美國加速-技術演進與行業應用深度解析

在當今數據驅動的時代&#xff0c;遞歸查詢已成為處理層級數據的核心技術&#xff0c;尤其在美國科技領域獲得廣泛應用。本文將深入解析遞歸查詢在美國加速發展的關鍵因素&#xff0c;包括技術演進、行業應用場景以及性能優化策略&#xff0c;幫助讀者全面理解這一重要技術趨勢…

【AIGC專欄】WebUI實現圖片的縮放

圖片的縮放包含如下的各類不同的縮放模型。 Lanczos Lanczos重采樣是一種數學上精確的方法,用于圖像放大或縮小。它使用了一種稱為 sinc 函數的數學公式,可以在保留圖像細節的同時減少鋸齒效應。 Nearest 最近鄰插值是一種簡單的圖像放大方法,通過復制最近的像素值來填充新…

Libevent(4)之使用教程(3)配置

Libevent(4)之使用教程(3)配置事件 Author: Once Day Date: 2025年7月27日 一位熱衷于Linux學習和開發的菜鳥&#xff0c;試圖譜寫一場冒險之旅&#xff0c;也許終點只是一場白日夢… 漫漫長路&#xff0c;有人對你微笑過嘛… 本文檔翻譯于&#xff1a;Fast portable non-bl…

若依前后端分離版學習筆記(三)——表結構介紹

前言&#xff1a; 這一節將ruoyi框架中數據庫中的表結構過一遍&#xff0c;查看都有哪些表及其表結構及關聯關系&#xff0c;為后續代碼學習做準備。 一 代碼生成表記錄代碼生成的業務表及相關字段1 代碼生成業務表 CREATE TABLE gen_table (table_id bigint(20) NOT NULL AUTO…