React Hook源码笔记(六):副作用钩子-useInsertionEffect

117 阅读1分钟

博客:pionpill
官方文档: react.dev/reference/r…

这个钩子是为 CSS-in-JS 打造的

目前主流的 CSS-in-JS 实现方案有三种:

  • 编译器静态提取到 CSS 文件,例如:styled-component
  • 内联样式,例如 <div style={{ opacity: 1 }}>
  • 运行时注入 <style> 标签

前两种是 React 官方建议的方案,第三种可以运行时动态改变 CSS 样式,但是有两个缺陷:

  • 运行时注入会使浏览器频繁地重新计算样式。
  • 如果在 React 生命周期中某个错误的时机进行运行时注入,它可能会非常慢。

第一个缺陷没法解决,是动态改变的必然代价,useInsertionEffect 可以解决第二个问题,指定注入的生命周期。

和 useLayoutEffect 有点类似,useInsertionEffect 也会在固定的时机运行。

具体实现

实现上非常简单,只有打的标签不同(✨约2542行):

function mountInsertionEffect(
  create: () => (() => void) | void,
  deps: Array<mixed> | void | null,
): void {
  mountEffectImpl(UpdateEffect, HookInsertion, create, deps);
}

function updateInsertionEffect(
  create: () => (() => void) | void,
  deps: Array<mixed> | void | null,
): void {
  return updateEffectImpl(UpdateEffect, HookInsertion, create, deps);
}

执行时机

HookInsertion 标记的副作用会在 commit 阶段的 commitMutationEffects 方法中被执行,具体执行方法是 commitHookEffectListMount。细节不再展开,处理逻辑和前面的大致相同。

commitMutationEffects 处于替换阶段树的前一阶段,在此阶段应用动态样式可以减小对 react 其他事务的影响。

本人没使用过这个钩子,所以知道的很少。希望大佬补充一些应用场景。