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

React源碼分析之useCallback與useMemo及useContext詳解

 更新時間:2022年11月05日 08:31:11   作者:goClient1992  
這篇文章主要介紹了React useCallback與useMemo及useContext源碼分析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧

熱身準備

useCallbackuseMemo是一樣的東西,只是入參有所不同。

useCallback緩存的是回調函數,如果依賴項沒有更新,就會使用緩存的回調函數;

useMemo緩存的是回調函數的return,如果依賴項沒有更新,就會使用緩存的return

官網有這樣一段描述useCallback(fn, deps)相當于useMemo(() => fn, deps)。

所以這里,只以useCallback為例進行分析。

初始化mount

mountCallback

如果各位看官是系列文章第一篇開始看的,看到這里估計就無壓力,mountCallback就這幾行代碼,筆者沒有做精簡。

function mountCallback(callback, deps) {
  // 初始化hook結構
  var hook = mountWorkInProgressHook();
  // 使用者傳進來的依賴數組
  var nextDeps = deps === undefined ? null : deps;
  // 以數組的形式將回調和依賴數組存儲到對應fiber.memoizedState.hook.moeoizedState
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

更新 update

function updateCallback(callback, deps) {
  var hook = updateWorkInProgressHook();
  var nextDeps = deps === undefined ? null : deps;
  var prevState = hook.memoizedState;
  if (prevState !== null) {
    if (nextDeps !== null) {
      var prevDeps = prevState[1];
      if (areHookInputsEqual(nextDeps, prevDeps)) {
        return prevState[0];
      }
    }
  }
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

updateCallback就這幾行代碼,沒有刪減,代碼意圖也很簡單,如果依賴數組deps沒有變化,或者deps=[]的情況下,會返回之前緩存的回調函數,否則就更新對應fiber.memoizedState.hook.memoizedState并返回新的回調函數。

使用場景

就筆者的所見所聞,存在兩種極端情況,一種開發(fā)者在開發(fā)時,不管什么函數,什么數據都喜歡使用useCallback,useMemo進行一層包裹。還有一種開發(fā)者不管什么情況都不會考慮使用useCallback,useMemo。

不用說,這兩種做法都是有問題的。第一種做法,還不知道是之所以會出現這樣的問題,根本原因還是很多開發(fā)者并不明白這兩個hook的原理和使用場景。

首先,我們要明確函數組件在每一次更新時,都會執(zhí)行函數組件,函數組件內部的所有方法,所有值都會重新聲明,重新計算。這兩個hook的出現就是為了優(yōu)化這種情況,避免不必要的浪費。而這兩個hook的做法就是通過將函數或者值存儲在對應的fiber.memoizedState.hook.memoizedState上,在下次更新時,根據依賴項是否變化來決定是否要用緩存值,還是新的傳進來的值。

這時候可能有人疑惑既然都會更新,那我全部包裹起來有什么不好?筆者認為都進行包裹主要的問題是,如果一個函數足夠簡單,從新聲明可能性能消耗會比包裹后存儲在hook.memoizedState的消耗更小。

這里,筆者根據自己看源碼的心得,列舉下這兩個hook的使用場景:

  • 如果子組件比較復雜,可以考慮使用useCallback進行包裹;
  • 如果函數組件中某個值需要大量的計算才能得出,可以考慮使用useMemo進行包裹;
  • 如果某個函數是子組件的props,可以考慮使用useCallback進行包裹(配合React.memo使用);
  • 自定義hooks中復雜邏輯可以考慮使用useCallbackuseMemo進行包裹;

相關參考視頻講解:傳送門

總結

這兩個hook原理還是很簡單的,因為是系列文章,很多內容和前面文章都重復了,所以導致這篇都沒啥能寫的了。總結下原理:

這兩個hook的做法就是通過將函數或者值存儲在對應的fiber.memoizedState.hook.memoizedState上,在下次更新時,根據依賴項是否變化來決定是要用緩存值,還是新的傳進來的值。

雖然useCallbackuseMemo是為了優(yōu)化性能出現的,但是各位看官也不要盲目使用,畢竟這兩個hook本身也會帶來開銷。

看完這篇文章, 我們可以弄明白下面這幾個問題:

  • useCallbackuseMemo的區(qū)別?
  • useCallbackuseMemo的使用場景有哪些?
  • useCallbackuseMemo是做什么的?
  • useCallbackuseMemo是怎么實現優(yōu)化性能的?

熱身準備

useContext可以幫助我們跨越組件層級直接傳遞變量,避免了在每一個層級手動的傳遞 props 屬性,實現共享,要配合createContext使用。

createContext

createContext主要功能是創(chuàng)建一個context,提供ProviderConsumer。Provider主要將context內容暴露出來,Consumer可以拿到對應contextProvider暴露的內容使用。

示例代碼:

export const Context = createContext(null)
<Context.Provider value='initialValue'>
  <Context.Consumer>
    {(v) => {      return <h2>{v}</h2>
    }}  </Context.Consumer>
</Context.Provider>

Provider

<Context.Provider>在渲染時,beginWork階段,會執(zhí)行

pushProvider(workInProgress, newValue);

它會將Providerprop上的value字段存到context._currentValue中。

Consumer

<Context.Consumer>在渲染時,beginWork階段,會執(zhí)行

prepareToReadContext(workInProgress, renderLanes);
var newValue = readContext(context, newProps.unstable_observedBits);

通過上面代碼可以拿到Providerprop上的value。

值得注意的是, Consumer標簽下包裹的必須是一個函數,如果不是函數會報錯。 Consumer會將拿到的value作為函數的參數傳入函數中去使用。如同上面示例代碼中獲取到的v。

useContext

useContext需要將createContext創(chuàng)建的Context作為參數進行調用。

值得一提的是,前面講的hook在初始化和更新時會有兩套不同函數執(zhí)行。但是在useContext只有一個,也就是useContext在初始化和更新時執(zhí)行的是一套代碼。

初始化mount&更新update

useContextmount時主要會調用readContext函數:

function readContext(context, observedBits) {
  var contextItem = {
    context: context,  // 傳入的context
    observedBits: resolvedObservedBits,  // 觀察范圍(默認全部update)
    next: null
  };
  lastContextDependency = contextItem;
  currentlyRenderingFiber.dependencies = {
    lanes: NoLanes,
    firstContext: contextItem,
    responders: null
  };
  } else {
    // Append a new context item.    lastContextDependency = lastContextDependency.next = contextItem;
  }
  return  context._currentValue ;
}

精簡了下代碼,可以看到,readContext會創(chuàng)建一個contextItem并以鏈表的結構記錄在對應fiber.dependencies上,最后將Providerprop上的value返回。

總結

useContext的原理類似于觀察者模式。Provider是被觀察者, ConsumeruseContext是觀察者。當Provider上的值發(fā)生變化, 觀察者是可以觀察到的,從而同步信息給到組件。

主要使用場景就是多層級組件值的傳遞,如果值較多可以考慮配合useReducer使用。

看完這篇文章, 我們可以弄明白下面這個問題:

useContext的原理是什么?

到此這篇關于React源碼分析之useCallback與useMemo及useContext詳解的文章就介紹到這了,更多相關React useCallback useMemo useContext內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 使用react render props實現倒計時的示例代碼

    使用react render props實現倒計時的示例代碼

    這篇文章主要介紹了使用react render props實現倒計時的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • React根據配置生成路由的示例代碼

    React根據配置生成路由的示例代碼

    React路由看似只能由Route組件包裹組件的結構來構成,但是其實也可以通過編寫路由數組配置然后通過數組循環(huán)來生成Route組件包裹組件的結構,所以本文給大家介紹了React根據配置生成路由的方法,需要的朋友可以參考下
    2024-11-11
  • 解決React報錯Cannot assign to 'current' because it is a read-only property

    解決React報錯Cannot assign to 'current'

    這篇文章主要為大家介紹了React報錯Cannot assign to 'current' because it is a read-only property的解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • React四級菜單的實現

    React四級菜單的實現

    本文主要介紹了React四級菜單的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • React事件綁定詳解

    React事件綁定詳解

    這篇文章主要為大家介紹了React事件綁定,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • React學習筆記之事件處理(二)

    React學習筆記之事件處理(二)

    這篇文章主要跟大家介紹了關于React中事件處理的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習React具有一定的參考學習價值,需要的朋友們下面跟著小編一起來學習學習吧。
    2017-07-07
  • React?Fiber構建源碼解析

    React?Fiber構建源碼解析

    這篇文章主要為大家介紹了React?Fiber構建源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • react入門級詳細筆記

    react入門級詳細筆記

    這篇文章講述了React的基本介紹,基本使用和React相關js庫.通過這篇文章可以入門React的使用,可以快速上手使用React進行代碼的編寫
    2021-06-06
  • React 中的 useContext使用方法

    React 中的 useContext使用方法

    這篇文章主要介紹了React中的useContext使用,使用useContext在改變一個數據時,是通過自己逐級查找對比改變的數據然后渲染,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • React高階組件使用教程詳解

    React高階組件使用教程詳解

    高階組件就是接受一個組件作為參數并返回一個新組件(功能增強的組件)的函數。這里需要注意高階組件是一個函數,并不是組件,這一點一定要注意,本文給大家分享React 高階組件HOC使用小結,一起看看吧
    2022-12-12

最新評論

常州市| 汪清县| 井冈山市| 松原市| 彭阳县| 乌拉特后旗| 始兴县| 漯河市| 长泰县| 通江县| 苍梧县| 平乐县| 呼玛县| 高邑县| 香格里拉县| 夹江县| 山东省| 精河县| 剑川县| 辽阳县| 芦山县| 安达市| 双江| 石泉县| 得荣县| 东乌珠穆沁旗| 太和县| 榆林市| 库伦旗| 光山县| 武安市| 赣榆县| 合山市| 邢台市| 怀仁县| 江都市| 丹阳市| 江西省| 新源县| 赞皇县| 屯留县|