55.React学习笔记.hook 原理浅析

在讲hook原理之前,我们需要先简单了解一下Fiber。

一.Fiber

React16推出的,用于提高当前浏览器显示界面性能的东西,减少卡顿等待。

我们电脑屏幕都有一个刷新率(Hz),电脑屏幕上的东西,CPU提供数据,GPU将其绘制出来;
电脑屏幕按固定的频率,从缓存中取出(帧)并显示;缓存防止屏幕出现撕裂 ;
浏览器刷新频率一般与电脑一致,浏览器根据电脑传来的vsync(同步信号)来刷新。

  1. GUI渲染和JS代码执行(还有用户事件响应,键盘事件响应,requestAnimationFrame(),layout,paint)是在同一个线程的,互斥,最好在一帧中将所有操作做完。若一直执行JS代码,那GUI就一直得不到渲染,然后就会保持上一帧的图像。耗费时间长,也就意味着明显的卡顿;
  2. 早期React中,点击按钮后,有大量组件生成或更新,会大量占用浏览器刷新时间;这些耗时操作,都是在上一步中,且在一帧时间内,JS线程完成后才执行的;
  3. 为了解决上述问题, 现在React把我们需要reconciliation协同的东西(diff,更新),切分成很多的Fiber
  4. Fiber为执行单元(执行碎片)。Fiber形成一个Fiber树,与ReactElement树结构一一对应;
  5. 现在控制权交给浏览器,让浏览器先做一些必须执行的用户/键盘/js代码响应等,若有剩余时间再做requestIdleCallback()=>Fiber碎片)来执行Fiber碎片。
    Fiber源码去react-reconciler中,东西太多,先打个标记,在开发过程如果有需求再做深入。

二.useState Hook原理

现在举个useState Hook的例子。


image.png
  1. useState的本质是dispatcher.useState(initialState)
    ,也就是resolveDispatcher();
image.png
  1. resolveDispatch方法返回的dispatcher来自于ReactCurrentDispatcher.current。
image.png
  1. ReactCurrentDispatcher中的Dispatcher又来自于'react-reconciler/src/ReactFiberHooks'中。
  1. 具体Dispatcher如下:
export type Dispatcher = {|
  readContext<T>(
    context: ReactContext<T>,
    observedBits: void | number | boolean,
  ): T,
  useState<S>(initialState: (() => S) | S): [S, Dispatch<BasicStateAction<S>>],
  useReducer<S, I, A>(
    reducer: (S, A) => S,
    initialArg: I,
    init?: (I) => S,
  ): [S, Dispatch<A>],
  useContext<T>(
    context: ReactContext<T>,
    observedBits: void | number | boolean,
  ): T,
  useRef<T>(initialValue: T): {|current: T|},
  useEffect(
    create: () => (() => void) | void,
    deps: Array<mixed> | void | null,
  ): void,
  useLayoutEffect(
    create: () => (() => void) | void,
    deps: Array<mixed> | void | null,
  ): void,
  useCallback<T>(callback: T, deps: Array<mixed> | void | null): T,
  useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T,
  useImperativeHandle<T>(
    ref: {|current: T | null|} | ((inst: T | null) => mixed) | null | void,
    create: () => T,
    deps: Array<mixed> | void | null,
  ): void,
  useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,
  useResponder<E, C>(
    responder: ReactEventResponder<E, C>,
    props: Object,
  ): ReactEventResponderListener<E, C>,
  useDeferredValue<T>(value: T, config: TimeoutConfig | void | null): T,
  useTransition(
    config: SuspenseConfig | void | null,
  ): [(() => void) => void, boolean],
|};
image.png

image.png
  1. 当组件使用了hooks进行渲染的时候,就会调用renderWithHooks函数。


    image.png
  • 真实环境下:如图所示,分为挂载时,和更新时的HooksDispatcher。
image.png

image.png
  1. 使用useState,第一次运行时,如上图所示。 若workInProgressHook为空则初始化,给它赋值hook。
image.png

image.png
  1. mountState函数中,若useState传入的为函数,多了一步执行过程。
    hook的memorizedState和baseState都为initialState。
    如果我调用多次useState,就如mountWorkInPrograssHook函数中的一样,判断workInProgressHook不为null,则创建一个新的hook,并将其拼接到workInProgressHook的next中。最终形成一个链表。
image.png
  1. 等到执行setState时,才会用到queue这个值。

  2. 在dispatchAction中 ,Fiber和queue的值,都来自刚刚mountState函数中的currentlyRenderingFiber和queue。

image.png

image.png

image.png
  1. 在执行setState时,就是进行一个dispatchAction的操作。
    其中创建了一个update,代表了本次要更新的东西,更新的东西存放在action中,然后再放到update中。
    若执行多次,则放入链表中。
image.png
  1. 在NoWork没有工作的状态下,useState本质上用的是useReducer;若有工作,在空闲的时候再执行update。

若有多个hook同时使用,本质上是以链表的形式,一个个保存hooks的。
不能在if中使用hook,因为其是个链表,可能数据会错乱。

东西太多了,可能看的有点乱,以后有需求再反复深入。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353