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

React中useMemo和useCallback的使用小結(jié)

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

前言

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

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

我們先看一個(gè)簡(jiǎn)單的例子:

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

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

  // 每次渲染都會(huì)重新執(zhí)行filter
  const filterList = list.filter(item => {
  // 測(cè)試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 改變導(dǎo)致組件重新渲染時(shí),filterList 也會(huì)重新計(jì)算。如果 list 很大或者過(guò)濾邏輯復(fù)雜,這種不必要的計(jì)算就會(huì)影響性能。同樣,如果我們將一個(gè)函數(shù)作為 prop 傳遞給子組件,每次父組件渲染都會(huì)生成一個(gè)新函數(shù),導(dǎo)致子組件(即使使用 React.memo)也無(wú)法避免重新渲染。這正是 useMemouseCallback 要解決的問(wèn)題。

效果圖

20263282313081.gif (1718×988)

2. useMemo:緩存計(jì)算結(jié)果

useMemo 用于緩存一個(gè)計(jì)算后的值,只有當(dāng)依賴項(xiàng)發(fā)生變化時(shí),才會(huì)重新計(jì)算。

2.1 基本用法

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

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

改進(jìn)上面的例子:

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 變化時(shí)才重新過(guò)濾
  const filterList = useMemo(() => {
    console.log('filter執(zhí)行了'); // 依賴變化時(shí)打印
    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>
  );
}

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

效果圖

20263282419971.gif (1772×938)

2.3 緩存昂貴計(jì)算

假設(shè)有一個(gè)非常耗時(shí)的函數(shù) slowSum

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

我們可以用 useMemo 將其結(jié)果緩存起來(lái):

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

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

2.4 小結(jié)

  • useMemo 適用于需要緩存計(jì)算結(jié)果的場(chǎng)景,比如過(guò)濾、排序、復(fù)雜數(shù)學(xué)運(yùn)算等。
  • 依賴數(shù)組要正確填寫(xiě),避免遺漏或多余依賴。
  • 不要濫用,如果計(jì)算本身不昂貴,就沒(méi)有必要緩存。

3. useCallback:緩存函數(shù)引用

在React中,函數(shù)組件每次渲染都會(huì)重新創(chuàng)建內(nèi)部定義的函數(shù)。如果這個(gè)函數(shù)作為 prop 傳遞給子組件,即使子組件使用了 React.memo,也會(huì)因?yàn)槊看胃附M件傳遞的函數(shù)引用不同而導(dǎo)致子組件重新渲染。useCallback 就是用來(lái)緩存函數(shù)引用的。

3.1 基本用法

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

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

先看一個(gè)沒(méi)有優(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 渲染,這里都會(huì)生成一個(gè)新函數(shù)
  const handleClick = () => {
    console.log('點(diǎn)擊了');
  };

  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 變化時(shí)才會(huì)重新渲染。但由于 handleClick 每次都是新函數(shù),memo 淺比較發(fā)現(xiàn) handleClick 引用變了,導(dǎo)致子組件也會(huì)重新渲染。即使點(diǎn)擊的是 num 按鈕,子組件依然會(huì)渲染。

效果圖,可以看到當(dāng)我們點(diǎn)擊nums組件時(shí),我們的子組件依然會(huì)執(zhí)行

20263282503315.gif (1892×964)

使用 useCallback 緩存 handleClick

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

現(xiàn)在點(diǎn)擊 num 按鈕,handleClick 引用不變,子組件就不會(huì)重新渲染。

效果圖,可以看到這個(gè)適合當(dāng)我們點(diǎn)擊nums組件,子組件就不會(huì)執(zhí)行了

20263282552951.gif (1688×840)

3.3 依賴項(xiàng)的作用

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

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

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

3.4 小結(jié)

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

4. useMemo 與 useCallback 的關(guān)系

  • useMemo 緩存的是,useCallback 緩存的是函數(shù)。
  • 實(shí)際上,useCallback(fn, deps) 等價(jià)于 useMemo(() => fn, deps)。
  • 兩者都是通過(guò)閉包和依賴追蹤來(lái)實(shí)現(xiàn)緩存,目的都是減少不必要的計(jì)算或渲染。

5. 常見(jiàn)誤區(qū)與注意事項(xiàng)

5.1 依賴數(shù)組要完整

無(wú)論是 useMemo 還是 useCallback,都要確保依賴數(shù)組中包含了所有在回調(diào)/計(jì)算中使用的響應(yīng)式值(props、state、context等)。否則會(huì)因閉包捕獲舊值而產(chǎn)生 bug??梢允褂?eslint-plugin-react-hooks 自動(dòng)檢查依賴。

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

只有在確實(shí)存在性能瓶頸時(shí)才使用這兩個(gè) Hook。濫用會(huì)增加代碼復(fù)雜度,且緩存本身也有開(kāi)銷??梢酝ㄟ^(guò) React DevTools 的 Profiler 來(lái)識(shí)別需要優(yōu)化的組件。

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

如果 useCallback 的回調(diào)函數(shù)依賴于外部狀態(tài),但依賴數(shù)組為空,則函數(shù)內(nèi)部的變量會(huì)一直保持初始值,可能導(dǎo)致 bug。一定要根據(jù)實(shí)際依賴填寫(xiě)數(shù)組。

6. 總結(jié)

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

通過(guò)合理使用這兩個(gè) Hook,我們可以讓 React 應(yīng)用在復(fù)雜場(chǎng)景下依然保持流暢。希望本文能幫助你深入理解 useMemouseCallback,并在實(shí)際項(xiàng)目中正確應(yīng)用它們。

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

相關(guān)文章

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

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

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

    React錯(cuò)誤的習(xí)慣用法分析詳解

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

    React如何使用sortablejs實(shí)現(xiàn)拖拽排序

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

    全棧輕量級(jí)搭配之Remix Prisma Sqlite使用分析

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

    React Native項(xiàng)目中使用Lottie動(dòng)畫(huà)的方法

    這篇文章主要介紹了React Native 實(shí)現(xiàn)Lottie動(dòng)畫(huà)的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • react?Table準(zhǔn)備Spin?Empty?ConfigProvider組件實(shí)現(xiàn)

    react?Table準(zhǔn)備Spin?Empty?ConfigProvider組件實(shí)現(xiàn)

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

    React前端DOM常見(jiàn)Hook封裝示例下

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

    React為什么需要Scheduler調(diào)度器原理詳解

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

    React Hook Form 概述及使用詳解

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

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

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

最新評(píng)論

朝阳市| 镇巴县| 琼海市| 宜丰县| 会泽县| 龙井市| 甘孜县| 鹰潭市| 安吉县| 称多县| 嘉义县| 保山市| 页游| 保康县| 康乐县| 福州市| 芒康县| 青州市| 延寿县| 十堰市| 广南县| 玉溪市| 马边| 弥渡县| 宁明县| 修水县| 南陵县| 汕头市| 油尖旺区| 昭平县| 隆德县| 长汀县| 威海市| 渑池县| 新乡市| 蕲春县| 错那县| 丁青县| 台南县| 大安市| 白朗县|