最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React中useMemo和useCallback的使用小結

 更新時間:2026年03月02日 08:27:25   作者:不會敲代碼1  
本文主要介紹了深入理解React中useMemo和useCallback的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

在React函數組件中,每次狀態(tài)更新都會導致整個組件函數重新執(zhí)行。如果組件內部有復雜的計算或者傳遞了回調函數給子組件,可能會引發(fā)不必要的性能開銷。React為我們提供了兩個重要的Hook:useMemouseCallback,用于緩存計算結果和函數引用,從而優(yōu)化組件性能。本文將從淺入深,結合實際代碼,帶你徹底理解這兩個Hook的使用場景和原理。

1. 性能優(yōu)化的必要性

我們先看一個簡單的例子:

function App() {
  const [count, setCount] = useState(0);
  const [keyword, setKeyword] = useState('');

  const list = ['apple', 'banana', 'orange', 'pear'];

  // 每次渲染都會重新執(zhí)行filter
  const filterList = list.filter(item => {
  // 測試fliter是否執(zhí)行
  console.log("filter執(zhí)行了")
  return item.includes(keyword) 
  });

  return (
    <div>
      <input value={keyword} onChange={e => setKeyword(e.target.value)} />
      <button onClick={() => setCount(count + 1)}>count: {count}</button>
      <ul>
        {filterList.map(item => <li key={item}>{item}</li>)}
      </ul>
    </div>
  );
}

這里 filterList 依賴于 keyword,但每次 count 改變導致組件重新渲染時,filterList 也會重新計算。如果 list 很大或者過濾邏輯復雜,這種不必要的計算就會影響性能。同樣,如果我們將一個函數作為 prop 傳遞給子組件,每次父組件渲染都會生成一個新函數,導致子組件(即使使用 React.memo)也無法避免重新渲染。這正是 useMemouseCallback 要解決的問題。

效果圖

20263282313081.gif (1718×988)

2. useMemo:緩存計算結果

useMemo 用于緩存一個計算后的值,只有當依賴項發(fā)生變化時,才會重新計算。

2.1 基本用法

const cachedValue = useMemo(computeFn, dependencies);
  • computeFn:純函數,返回需要緩存的值。
  • dependencies:依賴項數組,當任意依賴項變化時,重新執(zhí)行 computeFn

2.2 優(yōu)化列表過濾

改進上面的例子:

import { useState, useMemo } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  const [keyword, setKeyword] = useState('');
  const list = ['apple', 'banana', 'orange', 'pear'];

  // 只有 keyword 變化時才重新過濾
  const filterList = useMemo(() => {
    console.log('filter執(zhí)行了'); // 依賴變化時打印
    return list.filter(item => item.includes(keyword));
  }, [keyword]);

  return (
    <div>
      <input value={keyword} onChange={e => setKeyword(e.target.value)} />
      <button onClick={() => setCount(count + 1)}>count: {count}</button>
      <ul>
        {filterList.map(item => <li key={item}>{item}</li>)}
      </ul>
    </div>
  );
}

現在,點擊 count 按鈕不會觸發(fā) filter 重新執(zhí)行,只有輸入框改變時才會。

效果圖

20263282419971.gif (1772×938)

2.3 緩存昂貴計算

假設有一個非常耗時的函數 slowSum

function slowSum(n) {
  console.log('計算中...');
  let sum = 0;
  for (let i = 0; i < n * 1000000; i++) {
    sum += i;
  }
  return sum;
}

我們可以用 useMemo 將其結果緩存起來:

const [num, setNum] = useState(0);
const result = useMemo(() => slowSum(num), [num]);

這樣只有當 num 變化時才會重新計算,其他狀態(tài)變化不會觸發(fā) slowSum,這樣做我們就可以節(jié)約成本。

2.4 小結

  • useMemo 適用于需要緩存計算結果的場景,比如過濾、排序、復雜數學運算等。
  • 依賴數組要正確填寫,避免遺漏或多余依賴。
  • 不要濫用,如果計算本身不昂貴,就沒有必要緩存。

3. useCallback:緩存函數引用

在React中,函數組件每次渲染都會重新創(chuàng)建內部定義的函數。如果這個函數作為 prop 傳遞給子組件,即使子組件使用了 React.memo,也會因為每次父組件傳遞的函數引用不同而導致子組件重新渲染。useCallback 就是用來緩存函數引用的。

3.1 基本用法

const cachedFn = useCallback(fn, dependencies);
  • fn:需要緩存的函數。
  • dependencies:依賴項數組,當依賴變化時,重新創(chuàng)建函數。

3.2 配合 React.memo 優(yōu)化子組件

先看一個沒有優(yōu)化的例子:

import { useState, memo } from 'react';

const Child = memo(({ count, handleClick }) => {
  console.log('子組件渲染了');
  return <div onClick={handleClick}>子組件 count: {count}</div>;
});

export default function App() {
  const [count, setCount] = useState(0);
  const [num, setNum] = useState(0);

  // 每次 App 渲染,這里都會生成一個新函數
  const handleClick = () => {
    console.log('點擊了');
  };

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>count+1</button>
      <button onClick={() => setNum(num + 1)}>num+1</button>
      <Child count={count} handleClick={handleClick} />
    </div>
  );
}

雖然 Childmemo 包裹,理論上只有 counthandleClick 變化時才會重新渲染。但由于 handleClick 每次都是新函數,memo 淺比較發(fā)現 handleClick 引用變了,導致子組件也會重新渲染。即使點擊的是 num 按鈕,子組件依然會渲染。

效果圖,可以看到當我們點擊nums組件時,我們的子組件依然會執(zhí)行

20263282503315.gif (1892×964)

使用 useCallback 緩存 handleClick

const handleClick = useCallback(() => {
  console.log('點擊了');
}, []); // 空依賴表示函數永遠不會重新創(chuàng)建

現在點擊 num 按鈕,handleClick 引用不變,子組件就不會重新渲染。

效果圖,可以看到這個適合當我們點擊nums組件,子組件就不會執(zhí)行了

20263282552951.gif (1688×840)

3.3 依賴項的作用

如果回調函數內部使用了某些狀態(tài),需要將這些狀態(tài)添加到依賴數組中,否則函數內部會一直使用舊的閉包值。

const handleClick = useCallback(() => {
  console.log('當前count:', count);
}, [count]); // 當 count 變化時,重新生成函數

這樣既能保證函數引用在 count 不變時穩(wěn)定,又能在 count 變化時獲取最新值。

3.4 小結

  • useCallback 主要用于將回調函數傳遞給經過 memo 優(yōu)化的子組件,避免不必要的重繪。
  • 如果回調函數不依賴任何組件狀態(tài),依賴數組可以為空。
  • 注意不要過度優(yōu)化,如果子組件很輕量或者渲染成本很低,不一定需要使用 useCallback。

4. useMemo 與 useCallback 的關系

  • useMemo 緩存的是useCallback 緩存的是函數。
  • 實際上,useCallback(fn, deps) 等價于 useMemo(() => fn, deps)。
  • 兩者都是通過閉包和依賴追蹤來實現緩存,目的都是減少不必要的計算或渲染。

5. 常見誤區(qū)與注意事項

5.1 依賴數組要完整

無論是 useMemo 還是 useCallback,都要確保依賴數組中包含了所有在回調/計算中使用的響應式值(props、state、context等)。否則會因閉包捕獲舊值而產生 bug??梢允褂?eslint-plugin-react-hooks 自動檢查依賴。

5.2 不要過早優(yōu)化

只有在確實存在性能瓶頸時才使用這兩個 Hook。濫用會增加代碼復雜度,且緩存本身也有開銷??梢酝ㄟ^ React DevTools 的 Profiler 來識別需要優(yōu)化的組件。

5.3 緩存穩(wěn)定但非“純”的函數

如果 useCallback 的回調函數依賴于外部狀態(tài),但依賴數組為空,則函數內部的變量會一直保持初始值,可能導致 bug。一定要根據實際依賴填寫數組。

6. 總結

  • useMemo 用于緩存計算值,避免每次渲染都重新執(zhí)行昂貴計算。
  • useCallback 用于緩存函數引用,配合 React.memo 避免子組件不必要的重新渲染。
  • 兩者都需要指定依賴項,確保緩存內容在依賴變化時更新。
  • 性能優(yōu)化應當有的放矢,先測量后優(yōu)化,不要盲目使用。

通過合理使用這兩個 Hook,我們可以讓 React 應用在復雜場景下依然保持流暢。希望本文能幫助你深入理解 useMemouseCallback,并在實際項目中正確應用它們。

到此這篇關于React中useMemo和useCallback的具體使用的文章就介紹到這了,更多相關React useMemo useCallback內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • antd?upload上傳如何獲取文件寬高

    antd?upload上傳如何獲取文件寬高

    這篇文章主要介紹了antd?upload上傳如何獲取文件寬高問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • React錯誤的習慣用法分析詳解

    React錯誤的習慣用法分析詳解

    這篇文章主要為大家介紹了React錯誤用法習慣分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • React如何使用sortablejs實現拖拽排序

    React如何使用sortablejs實現拖拽排序

    這篇文章主要介紹了React如何使用sortablejs實現拖拽排序問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 全棧輕量級搭配之Remix Prisma Sqlite使用分析

    全棧輕量級搭配之Remix Prisma Sqlite使用分析

    這篇文章主要為大家介紹了全棧輕量級搭配之Remix Prisma Sqlite使用示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • React Native項目中使用Lottie動畫的方法

    React Native項目中使用Lottie動畫的方法

    這篇文章主要介紹了React Native 實現Lottie動畫的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • react?Table準備Spin?Empty?ConfigProvider組件實現

    react?Table準備Spin?Empty?ConfigProvider組件實現

    這篇文章主要為大家介紹了react?Table準備Spin、Empty、ConfigProvider組件實現詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>
    2023-02-02
  • React前端DOM常見Hook封裝示例下

    React前端DOM常見Hook封裝示例下

    這篇文章主要為大家介紹了React前端DOM常見Hook封裝示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • React為什么需要Scheduler調度器原理詳解

    React為什么需要Scheduler調度器原理詳解

    這篇文章主要為大家介紹了React為什么需要Scheduler調度器原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React Hook Form 概述及使用詳解

    React Hook Form 概述及使用詳解

    React Hook Form是一個輕量、高性能、無依賴的表單庫,它通過 React Hooks 提供簡單直觀的 API 來處理表單狀態(tài)和驗證,本文將詳細介紹 React Hook Form 的功能、使用方法及其最佳實踐,感興趣的朋友一起看看吧
    2025-05-05
  • 基于React?Hooks的小型狀態(tài)管理詳解

    基于React?Hooks的小型狀態(tài)管理詳解

    本文主要介紹一種基于?React?Hooks?的狀態(tài)共享方案,介紹其實現,并總結一下使用感受,目的是在狀態(tài)管理方面提供多一種選擇方式。感興趣的小伙伴可以了解一下
    2021-12-12

最新評論

梁山县| 彰化市| 都兰县| 汕尾市| 科技| 商丘市| 宿州市| 革吉县| 津南区| 安康市| 胶南市| 玉龙| 竹北市| 双柏县| 洛浦县| 信阳市| 正阳县| 安丘市| 安阳县| 二连浩特市| 兴海县| 四川省| 奉节县| 南平市| 郁南县| 方正县| 日土县| 夹江县| 洛浦县| 都匀市| 唐河县| 特克斯县| 德安县| 卫辉市| 察雅县| 松原市| 贵溪市| 公主岭市| 应城市| 泰兴市| 正蓝旗|