useMemo

它和useCallback一樣,也是返回有記憶的值。


image.png
import React, { memo, useState } from "react";

function calcNumTotal(num) {
  console.log("calcNumTotal被執(zhí)行");
  let total = 0;
  for (let i = 1; i < num; i++) {
    total += i;
  }
  return total;
}

const App = memo(() => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h2>計(jì)算結(jié)果:{calcNumTotal(50)}</h2>
      <h2>count:{count}</h2>
      <button onClick={(e) => setCount(count + 1)}>點(diǎn)我加1</button>
    </div>
  );
});

export default App;

每一次點(diǎn)擊button, <h2>計(jì)算結(jié)果:{calcNumTotal(50)}</h2>就會被重新渲染,calcNumTotal函數(shù)會被執(zhí)行。50并沒有改變,所以沒必要反復(fù)地被進(jìn)行調(diào)用
這樣給定義一個total變量的化,不會被反復(fù)執(zhí)行

import React, { memo, useState } from "react";

function calcNumTotal(num) {
  console.log("calcNumTotal被執(zhí)行");
  let total = 0;
  for (let i = 1; i < num; i++) {
    total += i;
  }
  return total;
}

let total = calcNumTotal(50);

const App = memo(() => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h2>計(jì)算結(jié)果:{total}</h2>
      <h2>count:{count}</h2>
      <button onClick={(e) => setCount(count + 1)}>點(diǎn)我加1</button>
    </div>
  );
});

export default App;

但是把total定義在組件外面,再去使用,不合適,而且total直接寫死了。
把total定義在App里面,也是會被反復(fù)的調(diào)用。

import React, { memo, useState } from "react";

function calcNumTotal(num) {
  console.log("calcNumTotal被執(zhí)行");
  let total = 0;
  for (let i = 1; i < num; i++) {
    total += i;
  }
  return total;
}

const App = memo(() => {
  const [count, setCount] = useState(0);
  let total = calcNumTotal(50);

  return (
    <div>
      <h2>計(jì)算結(jié)果:{total}</h2>
      <h2>count:{count}</h2>
      <button onClick={(e) => setCount(count + 1)}>點(diǎn)我加1</button>
    </div>
  );
});

export default App;

這個時候就可以使用useMemo。useMomo傳入一個函數(shù),他優(yōu)化的是這個函數(shù)的返回值。

  let result = useMemo(() => {
    return calcNumTotal(50);
  }, []);

用useMemo對返回結(jié)果做一個優(yōu)化。
第二個傳入空數(shù)組代表對什么都不依賴。
如果依賴count,[count]代表count改變,我里面的函數(shù)再重新執(zhí)行。
寫空數(shù)組代表我useMomo里面的函數(shù)和誰都沒有關(guān)系,這個函數(shù)不會被重新調(diào)用。返回的result永遠(yuǎn)是同一個值。

useMemo 和 useCallback的對比


  function fn() {
    console.log("increment");
    setCount(count + 1);
  }

  const increment = useCallback(fn, []);
  const increment2 = useMemo(() => fn, []);
  /* 這兩個寫法相同。對什么都沒有依賴的時候,返回的值incrment都相同。一個是直接對函數(shù)做優(yōu)化,一個是對函數(shù)的返回結(jié)果做優(yōu)化 */

當(dāng)count發(fā)生改變的時候,useMemo里面的函數(shù)重新執(zhí)行,返回不同的結(jié)果。count改變的時候,里面的函數(shù)才會做一個執(zhí)行。

  let result = useMemo(() => {
    return calcNumTotal(count * 2);
  }, [count]);

總結(jié)1:

1.如果函數(shù)里面有大量的計(jì)算,每次render的時候使用結(jié)果,useMemo對這個函數(shù)要不要重新執(zhí)行進(jìn)行優(yōu)化。用useMemo包裹的化,不對任何進(jìn)行依賴,是不會反復(fù)執(zhí)行這個函數(shù)的,一直使用同一個值。

如果把這兩個傳遞給子組件,會不會有區(qū)別


image.png

<HelloWorld result={result}></HelloWorld>
其實(shí)沒有區(qū)別,因?yàn)樽咏M件傳遞的都是一個數(shù)字。
如果是calcNumTotal(50) 那么子組件只有渲染一次,因?yàn)檫@個結(jié)果是一定的,而且子組件用了memo包裹。這個時候無論是有沒有用useMomo包裹這個函數(shù),子組件都是不會被渲染的。
但是如果是calcNumTotal(count * 2),子組件是每次都會被渲染的。

以上都是沒有區(qū)別的。
以下情況會有區(qū)別

import React, { memo, useMemo, useState } from "react";

const HelloWorld = memo(function (props) {
  console.log("hellow");
  return <h2>HelloWorld</h2>;
});

const App = memo(() => {
  const [count, setCount] = useState(0);

  const info = { name: "why", age: 18 };
  return (
    <div>
      <h2>count:{count}</h2>
      <button onClick={(e) => setCount(count + 1)}>點(diǎn)我加1</button>
      <HelloWorld infp={info}></HelloWorld>
    </div>
  );
});

export default App;

當(dāng)count發(fā)生改變的時候,子組件會重新渲染。當(dāng)app函數(shù)重新執(zhí)行,const info ={}會重新定義一個新的對象,如果不希望重新給子組件渲染,就使用useMemo包裹

import React, { memo, useMemo, useState } from "react";

const HelloWorld = memo(function (props) {
  console.log("hellow");
  return <h2>HelloWorld</h2>;
});

const App = memo(() => {
  const [count, setCount] = useState(0);

  const info = useMemo(() => ({ name: "why", age: 18 }), []);
  return (
    <div>
      <h2>count:{count}</h2>
      <button onClick={(e) => setCount(count + 1)}>點(diǎn)我加1</button>
      <HelloWorld infp={info}></HelloWorld>
    </div>
  );
});

export default App;

總結(jié)2

對子組件傳遞相同內(nèi)容的對象時候,使用useMemo可以進(jìn)行性能優(yōu)化。不讓子組件進(jìn)行多次渲染!(傳入值是沒有去別的,用memo包裹的話,子組件是不會重新渲染的)

優(yōu)化的點(diǎn)是2個!?。?!
useCallback就是只有1個,給子組件傳遞一個函數(shù)的時候進(jìn)行性能優(yōu)化?。〔蛔屪咏M件進(jìn)行多次渲染!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容