如何使用 useMemo 和 memo 優化 React 應用性能?

使用 useMemomemo 優化 React 應用性能

在構建復雜的 React 應用時,性能優化是確保應用流暢運行的關鍵。React 提供了多種工具來幫助開發者優化組件的渲染和計算邏輯,其中 useMemomemo 是兩個非常有用的 Hook。本文將詳細介紹這兩個工具的使用方法及其應用場景。

1. useMemo 的介紹與使用

1.1 什么是 useMemo

useMemo 是一個 React Hook,用于記憶(緩存)某些計算結果,以避免不必要的重復計算。它接收兩個參數:一個返回值的計算函數和一個依賴項數組。只有當依賴項發生變化時,useMemo 才會重新計算并返回新的值;否則,它將返回之前緩存的結果。

1.2 useMemo 的語法
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • computeExpensiveValue(a, b) 是一個計算昂貴值的函數。
  • [a, b] 是依賴項數組,只有當這些依賴項發生變化時,useMemo 才會重新執行計算。
1.3 示例:優化總價計算

在你的 Test2.tsx 組件中,total 函數用于計算商品的總價。每次組件重新渲染時,total 都會重新計算。為了優化這一點,我們可以使用 useMemo 來緩存計算結果:

import React, { useState, useMemo } from 'react';export default function Test2() {const [search, setSearch] = useState('');const [list, setList] = useState([{ id: 1, name: '蘋果', price: 10, count: 1 },{ id: 2, name: '小米', price: 20, count: 1 },{ id: 3, name: '華為', price: 30, count: 1 },]);const handleAdd = (id: number) => {setList(list.map(item => item.id === id ? { ...item, count: item.count + 1 } : item));};const handleSub = (id: number) => {setList(list.map(item => item.count > 1 && item.id === id ? { ...item, count: item.count - 1 } : item));};// 使用 useMemo 緩存總價計算結果const total = useMemo(() => {return list.reduce((pre, cur) => pre + cur.price * cur.count, 0);}, [list]);return (<div><h1>父組件</h1><input type="text" value={search} onChange={(e) => setSearch(e.target.value)} /><table border={1} cellPadding={5} cellSpacing={0}><thead><tr><th>商品名稱</th><th>商品價格</th><th>商品數量</th></tr></thead><tbody>{list.map(item => (<tr key={item.id}><td>{item.name}</td><td>{item.price * item.count}</td><td><button onClick={() => handleAdd(item.id)}>+</button><span>{item.count}</span><button onClick={() => handleSub(item.id)}>-</button></td></tr>))}</tbody><tfoot><tr><th scope="row" colSpan={1}>總價</th><td>{total}</td></tr></tfoot></table></div>);
}

在這個例子中,useMemo 確保只有當 list 發生變化時才會重新計算 total,從而減少了不必要的計算開銷。

2. memo 的介紹與使用

2.1 什么是 memo

memo 是 React 提供的一個高階組件(HOC),用于防止子組件不必要的重新渲染。它通過比較當前和上次渲染的 props 來決定是否需要重新渲染組件。如果 props 沒有變化,則跳過渲染,直接復用之前的渲染結果。

2.2 memo 的語法
const MemoizedComponent = React.memo(MyComponent);
  • MyComponent 是你想要優化的組件。
  • React.memo 返回一個新的組件,該組件會在 props 沒有變化時不重新渲染。
2.3 示例:優化子組件渲染

假設我們有一個子組件 ProductItem,它負責顯示單個商品的信息。我們可以使用 memo 來優化這個組件,避免不必要的重新渲染:

import React from 'react';
import { memo } from 'react';interface ProductItemProps {product: { id: number; name: string; price: number; count: number };onAdd: () => void;onSub: () => void;
}const ProductItem: React.FC<ProductItemProps> = ({ product, onAdd, onSub }) => {console.log('ProductItem rendered');return (<tr key={product.id}><td>{product.name}</td><td>{product.price * product.count}</td><td><button onClick={onAdd}>+</button><span>{product.count}</span><button onClick={onSub}>-</button></td></tr>);
};// 使用 memo 包裝 ProductItem 組件
const MemoizedProductItem = memo(ProductItem);export default MemoizedProductItem;

在這個例子中,MemoizedProductItem 只會在其 props 發生變化時重新渲染,否則會復用之前的渲染結果,從而提高性能。

3. useMemomemo 的區別

  • 作用范圍

    • useMemo 用于優化組件內部的計算邏輯,減少不必要的計算。
    • memo 用于優化組件的渲染行為,減少不必要的重新渲染。
  • 使用場景

    • 當你在組件內部有復雜的計算邏輯時,可以使用 useMemo 來緩存計算結果。
    • 當你有一個子組件頻繁重新渲染但實際內容沒有變化時,可以使用 memo 來優化渲染性能。

4. 總結

useMemomemo 是 React 中非常強大的工具,能夠顯著提升應用的性能。合理使用它們可以幫助你避免不必要的計算和渲染,從而讓應用更加高效和流暢。希望本文能幫助你更好地理解和使用這兩個工具,為你的 React 應用帶來更好的用戶體驗。

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

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

相關文章

Agent Laboratory: Using LLM Agents as Research Assistants 論文簡介

加速機器學習研究的智能實驗室——Agent Laboratory 1. 引言 隨著人工智能技術的飛速發展&#xff0c;機器學習領域正以前所未有的速度推進科學發現和技術創新。然而&#xff0c;傳統的科學研究模式往往受到時間、資源和專業知識限制&#xff0c;阻礙了研究者們探索新想法的能…

【網絡協議】【http】【https】ECDHE-TLS1.2

【網絡協議】【http】【https】ECDHE-TLS1.2 ECDHE算法 1.客戶端和服務器端事先確定好使用哪種橢圓曲線&#xff0c;和曲線上的基點G&#xff0c;這兩個參數都是公開的&#xff0c; 雙方各自隨機生成一個隨機數作為私鑰d&#xff0c;并與基點 G相乘得到公鑰Q(QdG)&#xff0c…

規避路由沖突

路由沖突是指在網絡中存在兩個或多個路由器在進行路由選擇時出現矛盾&#xff0c;導致網絡數據包無法正確傳輸&#xff0c;影響網絡的正常運行。為了規避路由沖突&#xff0c;可以采取以下措施&#xff1a; 一、合理規劃IP地址 分配唯一IP&#xff1a;確保每個設備在網絡中都有…

項目實戰--網頁五子棋(游戲大廳)(3)

我們的游戲大廳界面主要需要包含兩個功能&#xff0c;一是顯示用戶信息&#xff0c;二是匹配游戲按鈕 1. 頁面實現 hall.html <!DOCTYPE html> <html lang"ch"> <head><meta charset"UTF-8"><meta name"viewport"…

大模型UI:Gradio全解11——Chatbot:融合大模型的聊天機器人(4)

大模型UI&#xff1a;Gradio全解11——Chatbot&#xff1a;融合大模型的聊天機器人&#xff08;4&#xff09; 前言本篇摘要11. Chatbot&#xff1a;融合大模型的多模態聊天機器人11.4 使用Blocks創建自定義聊天機器人11.4.1 簡單聊天機器人演示11.4.2 立即響應和流式傳輸11.4.…

【線性代數】行列式的概念

d e t ( A ) ∑ i 1 , i 2 , ? , i n ( ? 1 ) σ ( i 1 , ? , i n ) a 1 , i 1 a 2 , i 2 , ? , a n , i n det(A) \sum_{i_1,i_2,\cdots,i_n } (-1)^{\sigma(i_1,\cdots,i_n)} a_{1,i_1}a_{2,i_2},\cdots, a_{n,i_n} det(A)i1?,i2?,?,in?∑?(?1)σ(i1?,?,in?)a1…

關于php語言api接口開發的流程

確定接口需求&#xff1a;首先明確接口的功能和需求&#xff0c;包括輸入參數、輸出結果以及接口的業務邏輯。 設計接口路由&#xff1a;根據接口需求&#xff0c;設計具體的接口路由&#xff0c;即URL路徑&#xff0c;用于訪問接口。 搭建PHP環境&#xff1a;確保你的服務器上…

STM32 FreeRTOS內存管理簡介

在使用 FreeRTOS 創建任務、隊列、信號量等對象時&#xff0c;通常都有動態創建和靜態創建的方式。動態方式提供了更靈活的內存管理&#xff0c;而靜態方式則更注重內存的靜態分配和控制。 如果是1的&#xff0c;那么標準 C 庫 malloc() 和 free() 函數有時可用于此目的&#…

【Linux系統編程】—— 深度解析進程等待與終止:系統高效運行的關鍵

文章目錄 進程創建再次認識fork()函數fork()函數返回值 寫時拷貝fork常規?法以及調用失敗的原因 進程終?進程終止對應的三種情況進程常?退出?法_exit函數exit函數return退出 進程等待進程等待的必要性進程等待的?法 進程創建 再次認識fork()函數 fork函數初識&#xff1…

國產編輯器EverEdit -重復行

1 重復行 1.1 應用場景 在代碼或文本編輯過程中&#xff0c; 經常需要快速復制當前行&#xff0c;比如&#xff0c;給對象的多個屬性進行賦值。傳統的做法是&#xff1a;選中行-> 復制-> 插入新行-> 粘貼&#xff0c;該操作有4個步驟&#xff0c;非常繁瑣。 那有沒…

基于VSCode+CMake+debootstrap搭建Ubuntu交叉編譯開發環境

基于VSCodeCMakedebootstrap搭建Ubuntu交叉編譯開發環境 1 基于debootstrap搭建目標系統環境1.1 安裝必要軟件包1.2 創建sysroot目錄1.3 運行debootstrap1.4 掛載必要的虛擬文件系統1.5 進入目標系統1.6 使用目標系統&#xff08;以安裝zlog為例&#xff09;1.7 清理和退出 2 基…

NiceFish(美人魚)

前端有 3 個版本&#xff1a; 瀏覽器環境移動端環境Electron 環境 服務端有 2 個版本&#xff1a; SpringBoot 版本&#xff08;已實現基于 Apache Shiro 的 RBAC 權限控制&#xff09;SpringCloud 版本 1.主要依賴 名稱版本描述Angular16.2.0Angular 核心庫。PrimeNG16.2…

華為ENSP:STP和鏈路聚合的管理與配置

這里將不再過度闡述STP和鏈路聚合的理論知識&#xff0c;不清楚的同學可以去觀看Cisco文章中的理論知識 理論知識https://blog.csdn.net/2301_76341691/article/details/145166547?fromshareblogdetail&sharetypeblogdetail&sharerId145166547&sharereferPC&…

【PyCharm】連接 Git

【PyCharm】相關鏈接 【PyCharm】連接 Git【PyCharm】連接Jupyter Notebook【PyCharm】快捷鍵使用【PyCharm】遠程連接Linux服務器【PyCharm】設置為中文界面 要在 PyCharm 中連接 Git&#xff0c;確保您的開發環境已經安裝了 Git&#xff0c;并且 PyCharm 能夠訪問它。 以下…

dl學習筆記:(4)簡單神經網絡

&#xff08;1&#xff09;單層正向回歸網絡 bx1x2z100-0.2110-0.05101-0.051110.1 接下來我們用代碼實現這組線性回歸數據 import torch x torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype torch.float32) z torch.tensor([-0.2, -0.05, -0.05, 0.1]) w torch.…

三、華為交換機 Hybrid

一、Hybrid功能 Hybrid口既可以連接普通終端的接入鏈路&#xff08;類似于Access接口&#xff09;&#xff0c;又可以連接交換機間的干道鏈路&#xff08;類似于Trunk接口&#xff09;。它允許多個VLAN的幀通過&#xff0c;并可以在出接口方向將某些VLAN幀的標簽剝掉&#xff0…

Tensor 基本操作1 | PyTorch 深度學習實戰

目錄 創建 Tensor常用操作unsqueezesqueezeSoftmax代碼1代碼2代碼3 argmaxitem 創建 Tensor 使用 Torch 接口創建 Tensor import torch參考&#xff1a;https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html 常用操作 unsqueeze 將多維數組解套&#xf…

Grafana系列之面板接入Prometheus Alertmanager

關于Grafana的儀表板Dashboard&#xff0c;以及面板Panel&#xff0c;參考Grafana系列之Dashboard。可以直接在面板上創建Alert&#xff0c;即所謂的Grafana Alert&#xff0c;參考Grafana系列之Grafana Alert。除了Grafana Alert外&#xff0c;面板也可接入Prometheus Alertma…

Windows 上安裝 MongoDB 的 zip 包

博主介紹&#xff1a; 大家好&#xff0c;我是想成為Super的Yuperman&#xff0c;互聯網宇宙廠經驗&#xff0c;17年醫療健康行業的碼拉松奔跑者&#xff0c;曾擔任技術專家、架構師、研發總監負責和主導多個應用架構。 近期專注&#xff1a; RPA應用研究&#xff0c;主流廠商產…

LeetCode 2266.統計打字方案數:排列組合

【LetMeFly】2266.統計打字方案數&#xff1a;排列組合 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/count-number-of-texts/ Alice 在給 Bob 用手機打字。數字到字母的 對應 如下圖所示。 為了 打出 一個字母&#xff0c;Alice 需要 按 對應字母 i 次&#xff0c…