useInsertionEffect 用于在 DOM 变更之前注入样式,主要面向 CSS-in-JS 库作者。

useInsertionEffect Hook 详解

useInsertionEffect 用于在 DOM 变更之前注入样式,主要面向 CSS-in-JS 库作者。

// 基本语法

useInsertionEffect(() => {
  // 在 DOM 变更之前执行
  const style = document.createElement('style');
  style.textContent = css;
  document.head.appendChild(style);

  return () => {
    document.head.removeChild(style);
  };
}, [css]);

⚠️ 重要限制:

  • 不能访问 refs(此时 DOM 还未更新)
  • 不能调度状态更新
  • 仅用于样式注入

示例 1: 执行顺序

点击按钮查看执行顺序...

执行流程:

  1. useInsertionEffect - DOM 变更之前
  2. DOM 更新到页面
  3. useLayoutEffect - DOM 变更之后,浏览器绘制之前
  4. 浏览器绘制屏幕
  5. useEffect - 绘制完成之后

示例 2: 动态样式注入

这个盒子的样式通过 useInsertionEffect 注入
注意: 样式在 DOM 变更之前注入,确保元素渲染时样式已存在, 避免无样式闪烁(FOUC)。

示例 3: CSS-in-JS 简化实现

PRIMARY Card

使用 useInsertionEffect 注入样式

简化的 CSS-in-JS 流程:

  1. 生成唯一的 className
  2. 使用 useInsertionEffect 注入 style 标签
  3. 将 className 应用到元素

示例 4: 主题切换

主题演示区域

这个区域的颜色通过 CSS 变量控制,变量在 useInsertionEffect 中注入。

优势: 主题变量在 DOM 更新前注入,切换时没有闪烁。

使用建议

✅ 适用场景

  • CSS-in-JS 库开发
  • 动态样式注入
  • 主题系统实现
  • 样式库内部实现

❌ 不适用场景

  • 普通应用开发
  • DOM 操作
  • 数据获取
  • 状态更新

提示: 大多数开发者不需要直接使用此 Hook, 而是使用基于它构建的库(如 styled-components、Emotion)。