国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【1024用代碼改變世界】useMemo 和 useCallback|React.memo使用場(chǎng)景

這篇具有很好參考價(jià)值的文章主要介紹了【1024用代碼改變世界】useMemo 和 useCallback|React.memo使用場(chǎng)景。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

歡迎來(lái)到我的博客
??博主是一名大學(xué)在讀本科生,主要學(xué)習(xí)方向是前端。
??目前已經(jīng)更新了【Vue】、【React–從基礎(chǔ)到實(shí)戰(zhàn)】、【TypeScript】等等系列專欄
??目前正在學(xué)習(xí)的是?? R e a c t / 小程序 React/小程序 React/小程序??,中間穿插了一些基礎(chǔ)知識(shí)的回顧
??博客主頁(yè)??codeMak1r.小新的博客

本文被專欄【React–從基礎(chǔ)到實(shí)戰(zhàn)】收錄

const testcomponent = react.memo,前端面試,前端,javascript,react.js,前端性能優(yōu)化

??堅(jiān)持創(chuàng)作??,一起學(xué)習(xí)??,碼出未來(lái)???????!

前言

useMemo / useCallback都是React內(nèi)置的用于性能優(yōu)化的hook,它們常常被開(kāi)發(fā)人員用來(lái)包裹(緩存memory),但是真的是所有的數(shù)據(jù)、函數(shù)、變量都需要使用useMemo / useCallback去緩存嗎?
可直接看結(jié)論。

useMemo / useCallback都是用以性能優(yōu)化的hook,開(kāi)發(fā)者經(jīng)常擔(dān)心兩次渲染間的重復(fù)計(jì)算,而去過(guò)度使用useMemo / useCallback,擔(dān)心性能問(wèn)題的開(kāi)發(fā)者們,給幾乎每個(gè)變量都套上了useMemo,給每個(gè)函數(shù)都套上了useCallback……其實(shí)這是不可取的,這讓代碼看起來(lái)像是必須使用這兩個(gè)hook去優(yōu)化一樣,無(wú)處不在。

本文希望通過(guò)分析 useMemo/useCallback 的目的、方式、成本,以及具體使用場(chǎng)景,幫助開(kāi)發(fā)者正確的決定如何適時(shí)的使用他們。趕時(shí)間的讀者可以直接拉到底部看結(jié)論。

我們先從 useMemo/useCallback 的目的說(shuō)起。

何時(shí)應(yīng)該使用useMemo / useCallback ?

防止不必要的 effect

小新在編碼的過(guò)程中,如果effect有依賴的變量,我就會(huì)把effect里的內(nèi)容提到effect外面,包裝成一個(gè)函數(shù),再用useCallback去緩存這個(gè)函數(shù),那么只要這個(gè)變量不變化,effect依賴的這個(gè)函數(shù)也不會(huì)改變(不使用useCallback緩存的話,此函數(shù)的內(nèi)存地址可能會(huì)發(fā)生變化,哪怕其內(nèi)部不改變)。

const Component = () => {
  const a = React.useMemo(() => ({ test: 1 }), [])
  React.useEffect(() => {
    // dosomthing
  }, [a])
  return (
    <div>{a.test}</div>
  )
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Component />);

只有a的值改變時(shí),dosomthing才會(huì)重新觸發(fā),而a被useMemo緩存了,這就導(dǎo)致非必要時(shí),effect不會(huì)重新創(chuàng)建,這是好的優(yōu)化;

useCallback也是一樣的,(useCallback其實(shí)是useMemo的語(yǔ)法糖)

const Component = () => {
  const ajax = React.useCallback(() => {
    console.log('^ajax somthing^!')
  }, [])
  React.useEffect(() => {
    // dosomthing
    ajax()
  }, [ajax])
  return (
    <div></div>
  )
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Component />);

此代碼段中的Component組件,只有當(dāng)ajax函數(shù)變化時(shí)才會(huì)重新創(chuàng)建一個(gè)effect,這就導(dǎo)致,我們可以把僅需要在頁(yè)面首次加載時(shí)發(fā)送的ajax請(qǐng)求封裝成一個(gè)函數(shù),并且用useCallback優(yōu)化緩存下來(lái),這是好的優(yōu)化;

防止不必要的re-render

我們首先思考,當(dāng)什么情況出現(xiàn)時(shí),組件才會(huì)re-render

  • 當(dāng)本身的props或state改變時(shí);
  • context上下文的value改變時(shí),使用該值的組件都會(huì)重新render;
  • 當(dāng)父組件重新render時(shí),哪怕傳入子組件的props沒(méi)有發(fā)生改變,子組件(們)也會(huì)隨著父組件的render,重新render;

第三個(gè)re-render經(jīng)常被開(kāi)發(fā)者忽視,其實(shí)這一點(diǎn)很重要??!

例如,

const Component = () => {
  const [state, setState] = React.useState(1);

  const onClick = React.useCallback(() => {
    console.log('^click somthing^!')
  }, []);

  return (
	// 哪怕onClick使用了useCallback緩存優(yōu)化,但是自組件仍會(huì)re-render
    <Child onClick={onClick} />
  )
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Component />);

哪怕onClick使用了useCallback緩存優(yōu)化,但是自組件仍會(huì)re-render。這里的useCallback似乎是無(wú)效的。

那么,怎么讓其生效呢?

我們可以搭配React.memo去使用:

const PageMemoized = React.memo(Page);

React.memo本質(zhì)是一個(gè)HOC,它接受一個(gè)組件作為參數(shù)。被memo包裹的Page組件,會(huì)在Page組件的父組件Component重新render時(shí),對(duì)比傳入Page組件的props( 淺比較,復(fù)雜對(duì)象只比較第一層),若props沒(méi)有發(fā)生改變,則Pages組件就不會(huì)re-render

所以, 必須同時(shí)緩存 onClick 和組件本身,才能實(shí)現(xiàn) Page 不觸發(fā) re-render。

PageMemoized會(huì)在父組件重新render時(shí),淺比較傳入的onClick是否變化再?zèng)Q定PageMemoized組件是否需要re-render,但是onClick正好被useCallback緩存了,所以這里的子組件不會(huì)re-render(●–●)

但是,如果PageMemoized組件從父組件不止接受了onClick一個(gè)prop,那么前面的優(yōu)化就前功盡棄。比如,

// 省略重復(fù)代碼

<PageMemoized onClick={onClick} value={[1, 2, 3]} />

每次父組件重新re-render時(shí),傳入子組件的onClick函數(shù)雖然沒(méi)有改變(useCallback的功勞),但是value并沒(méi)有做任何緩存,此時(shí),子組件PageMemoized,還是逃脫不了re-render的命運(yùn)……

怎么解決呢?

// 省略重復(fù)代碼
const value = useMemo(() => {
  return [1, 2, 3]
}, [])

// ...
<PageMemoized onClick={onClick} value={[1, 2, 3]} />

這樣的話,value變量也被緩存起來(lái)了,父組件re-render時(shí),自組件并沒(méi)有re-render。

由此我們知道, 必須同時(shí)緩存 所有的prop 和組件本身,才能實(shí)現(xiàn)子組件 不觸發(fā) re-render。

如何判斷子組件是否需要緩存?

如果所有的子組件都需要緩存,那未免也太麻煩了……不光需要memo子組件,還需要將現(xiàn)有的props都進(jìn)行緩存,并且還包括了后續(xù)編碼可能出現(xiàn)的其他props……

除此之外,還有更嚴(yán)重的后果,如果項(xiàng)目中的組件緩存過(guò)多的話,可能會(huì)導(dǎo)致 項(xiàng)目在首次初始化時(shí)因?yàn)榻M件緩存被拖慢渲染時(shí)間。

所以,局部的,有選擇的去使用memo,比全局都使用memo更加恰當(dāng)、更加優(yōu)雅。

至于怎樣判斷組件的渲染成本,可以借助React Devtool等工具去判斷,或者根據(jù)開(kāi)發(fā)者經(jīng)驗(yàn)人工判斷。

防止不必要的計(jì)算

React官方文檔介紹:

useMemo返回一個(gè) memoized 值。
把“創(chuàng)建”函數(shù)和依賴項(xiàng)數(shù)組作為參數(shù)傳入 useMemo,它僅會(huì)在某個(gè)依賴項(xiàng)改變時(shí)才重新計(jì)算 memoized 值。這種優(yōu)化有助于避免在每次渲染時(shí)都進(jìn)行高開(kāi)銷的計(jì)算。

什么才是高開(kāi)銷呢?

借助前端經(jīng)典面試題提供的測(cè)試用例,對(duì)包含 250 個(gè) item 的數(shù)組 countries 進(jìn)行排序、渲染,并計(jì)算耗時(shí)。結(jié)果發(fā)現(xiàn),排序耗時(shí)僅用了4ms,而渲染這些List卻用了20ms,5倍的差距!而日常開(kāi)發(fā)中,大部分情況下都是,計(jì)算的數(shù)據(jù)更少,而渲染的組件更多。這也就說(shuō)明了, 大部分情況下,真正的性能瓶頸不是計(jì)算,而是渲染。 所以應(yīng)該把useMemo用在渲染昂貴的組件上,而不是計(jì)算上。

那為什么不給所有的組件都使用useMemo呢?前面也說(shuō)了,緩存會(huì)影響項(xiàng)目初始化的速度,而且可能會(huì)導(dǎo)致與PureComponent相同的問(wèn)題,傳入子組件的prop淺層并無(wú)變化,于是被useMemo包裹的子組件并不會(huì)re-render,但其實(shí)此時(shí)正需要它re-render。

結(jié)論

  1. 大部分的 useMemo 和 useCallback 都應(yīng)該移除,他們可能沒(méi)有帶來(lái)任何性能上的優(yōu)化,反而增加了程序首次渲染的負(fù)擔(dān),并增加程序的復(fù)雜性。
  2. 使用 useMemo 和 useCallback 優(yōu)化子組件 re-render 時(shí),必須同時(shí)滿足:
    • 子組件被React.memo 或 useMemo 緩存;
    • 子組件所有的prop都被緩存。
  3. 不推薦默認(rèn)給所有組件都使用緩存,大量組件初始化時(shí)被緩存,可能導(dǎo)致過(guò)多的內(nèi)存消耗,并影響程序初始化渲染的速度。

專欄訂閱入口【React–從基礎(chǔ)到實(shí)戰(zhàn)】文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-786263.html

到了這里,關(guān)于【1024用代碼改變世界】useMemo 和 useCallback|React.memo使用場(chǎng)景的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 理解 React 中的 useEffect、useMemo 與 useCallback

    理解 React 中的 useEffect、useMemo 與 useCallback

    先理解 useEffect 有助于學(xué)習(xí) useMemo 和 useCallback。因?yàn)?useMemo 和 useCallback 的實(shí)現(xiàn)實(shí)際上都是基于 useEffect 的。 useEffect 是 React 中的一個(gè)很重要的 Hook,用于執(zhí)行副作用操作。什么是副作用?簡(jiǎn)單來(lái)說(shuō),就是那些會(huì)改變函數(shù)外部變量或有外部可觀察影響的操作。useEffect 允許你在函

    2024年02月03日
    瀏覽(22)
  • useMemo和useCallback使用場(chǎng)景

    useMemo到底是做什么的,工作原理是什么。 簡(jiǎn)而言之,useMemo是用來(lái)緩存 計(jì)算屬性 的。 計(jì)算屬性其實(shí)是函數(shù)的返回值,或者說(shuō)指那些以返回一個(gè)值為目標(biāo)的函數(shù)。 有些函數(shù),需要我們手動(dòng)的去點(diǎn)擊,去完成一些動(dòng)作才觸發(fā)。而有些函數(shù),則是直接在渲染的時(shí)候就執(zhí)行,在DO

    2024年02月15日
    瀏覽(19)
  • React中useMemo的簡(jiǎn)單使用

    useMemo主要用來(lái)解決使用React hooks產(chǎn)生的無(wú)用渲染的性能問(wèn)題,用來(lái)做緩存用。 useMemo使用場(chǎng)景,比如有兩個(gè)變量(依賴項(xiàng)),只需要在其中一個(gè)變量變化時(shí)發(fā)生變化,否則拿緩存的值;或者其中另一個(gè)變量的變化不需要引起重新計(jì)算時(shí)使用。該屬性類似于vue中的計(jì)算屬性,有

    2024年02月13日
    瀏覽(25)
  • React useMemo 實(shí)際開(kāi)發(fā)使用小結(jié)

    React useMemo 實(shí)際開(kāi)發(fā)使用小結(jié)

    useMemo 的原理是基于 memoization 技術(shù)。當(dāng)你使用 useMemo 時(shí),它會(huì)在組件渲染過(guò)程中緩存函數(shù)的計(jì)算結(jié)果,并在下一次渲染時(shí),僅在依賴項(xiàng)(dependencies)發(fā)生變化時(shí)重新計(jì)算。如果依賴項(xiàng)沒(méi)有發(fā)生變化,則直接返回之前緩存的結(jié)果,避免不必要的重復(fù)計(jì)算。 在組件初次渲染時(shí),

    2024年02月16日
    瀏覽(20)
  • React.memo、shouldComponentUpdate、PureComponent的基本使用

    當(dāng)我們組件內(nèi)部有大量的計(jì)算是,避免組件內(nèi)部進(jìn)行不必要的重新渲染,使用React.memo進(jìn)行緩存組件,避免不必要的重新渲染 React.memo 是用來(lái)判斷是否需要重新渲染組件,和 shouldComponentUpdate 的區(qū)別是 shouldComponentUpdate 用于class組件方式,而 React.memo 用于 hooks 方式 語(yǔ)法 React.me

    2024年02月06日
    瀏覽(22)
  • react useState useEffect useMemo實(shí)際業(yè)務(wù)場(chǎng)景中的使用

    react useState useEffect useMemo實(shí)際業(yè)務(wù)場(chǎng)景中的使用

    下面的代碼實(shí)現(xiàn)了上面圖片的功能

    2024年02月16日
    瀏覽(25)
  • React 中的 useCallback 鉤子函數(shù)

    useCallback 鉤子函數(shù)有點(diǎn)像 useMemo 一樣可以備份信息,而 useCallback 只是備份函數(shù),除非某些參數(shù)發(fā)生變化,否則他不會(huì)重新運(yùn)行其中的代碼, 出現(xiàn)的問(wèn)題:運(yùn)行上述代碼后,當(dāng)我們?cè)谳斎肟蛑休斎霐?shù)字后,再去查看控制臺(tái)的日志我們可以看到打印出了 params change 的信息,這就

    2024年02月09日
    瀏覽(18)
  • [React]useMemoizedFn和useCallback對(duì)比

    useMemoizedFn文檔地址:https://ahooks.js.org/zh-CN/hooks/use-memoized-fn 在 React 中,自定義的 Hooks 內(nèi)部的函數(shù)在以下常見(jiàn)的幾種情況下會(huì)被重新賦值,導(dǎo)致更新引用: 組件重新渲染: 當(dāng)組件重新渲染時(shí),Hooks 內(nèi)部的函數(shù)會(huì)被重新執(zhí)行,從而導(dǎo)致函數(shù)的重新賦值和更新引用。 這意味著每

    2024年02月14日
    瀏覽(18)
  • 5.React.memo 性能優(yōu)化

    性能優(yōu)化, React.memo 2. React.memo類似純組件,可提高組件性能表現(xiàn)(類組件PureComponent)

    2024年02月11日
    瀏覽(24)
  • React Hook之useCallback 性能優(yōu)化

    React Hook之useCallback 性能優(yōu)化

    上文 對(duì)比之前的組件優(yōu)化說(shuō)明React.memo的作用我們說(shuō)了 React.memo的妙用 但是 它卻并非萬(wàn)能 我們來(lái)看這個(gè)情況 我們子組件代碼編寫(xiě)如下 這里 我們接收了父組件 props中的一個(gè) dom1funt 函數(shù) 然后點(diǎn)擊dom1funt按鈕 觸發(fā)這個(gè)dom1funt 然后 父組件代碼編寫(xiě)如下 父組件 我們定義了這個(gè)傳給

    2024年02月11日
    瀏覽(38)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包