先挖掘useEffect,useLayoutEffect的共性,被用于解决什么问题;
其次是发掘独特的个性,各自使用的场景,设计原理以及未来趋势等
相同点
使用方式
- useLayoutEffect的函数签名和useEffect,相同
- useEffect先调用mountEffect,再调用mountEffectImpl,useLayoutEffect会先调用mountLayoutEffectz再调用mountEffectImpl
从代码角度而言,虽然是两个函数,但是使用方式完全一致,一定程度上可相互替换
什么是函数签名呢
运用效果
都是用于处理副作用,这些副作用包括改变DOM,设置订阅,操作定时器等 看起来很像,但是在执行效果上仍然有些差异 React官方也给出建议: 如果不能掌握useLayoutEffect, 不妨直接用useEffect 在使用useEffect时遇到问题,再尝试使用useLayoutEffect
不同点
使用场景
举例:
上代码,出现页面闪烁的问题,当把useEffect改成useLayoutEffect问题就可以得到解决 小结:
- 大多数场景下可直接使用useEffect,但是代码引起页面闪烁就推荐使用useLayoutEffect处理
- 如果直接操作DOM样式,或引起DOM样式,更新的场景更推荐使用 useLayoutEffect
useEffect,useLayoutEffect内部调用的是同一个底层函数,为什么内部都是调用同一个函数,会有这样的区别呢?这里就要从Hooks的设计原理说起
设计原理
如下图:
Effect Hooks会有些不同,它涉及了一些额外的处理逻辑,每个Fiber的Hooks队列中保存了effect节点 而每个effect的类型都有可能不同,需要在适合的阶段去执行
回到底层代码,我们会发现只有第一参数和第二参数是不一样的,其中UpdateEffect, PassiveEffect, PassiveStaticEffect,就是Fiber的标记 HookPassive和HookLayout就是当前Effect的标记
标记为HookLayout的effect会在所有的DOM变更之后同步调用,所以可以使用它来去读DOM布局并同步触发重新渲染; 既然是同步,计算量较大的耗时任务必然会造成阻塞,所以需要根据实际情况酌情考虑,如果非必要情况下,使用标准的useEffect可以避免阻塞