710 字
4 分钟
useInsertionEffect

这个 Hook 不是给业务代码用的#

官方参考页第一段就是警告框:useInsertionEffect 是给 CSS-in-JS 库作者用的。如果你不是在写这类库、只是想插样式,你要的是 useEffect 或 useLayoutEffect。

所以这一篇的写法与前几篇不同:先说清它为什么存在,再说清什么时候不该碰它。

它解决的那个问题#

CSS-in-JS 的运行时注入会这样干:组件渲染时生成一条规则,比如 .btn_abc { color: red },然后把 <style> 插进文档。

时机放错,两个方向都难受:

  • 在渲染期间插,浏览器在并发更新下会逐帧重算样式,非常慢。
  • 在 useEffect 里插,其他 Effect 可能已经读过布局,读到的是旧样式算出来的结果。

useInsertionEffect 保证的是第二件事:等别的 Effect 跑起来时,<style> 已经就位。官方给它的定位是「在任何 layout Effect 触发之前,把元素插进 DOM」。

它不能假设 DOM 已经更新#

这条最常被写错。官方原文是:useInsertionEffect 可能在 DOM 更新之前运行,也可能在之后,你不该依赖 DOM 在某个特定时刻已经更新。

同样的原因,它跑的时候 ref 还没挂上,所以读不到节点、读不到布局。另外两条限制:只在客户端运行,服务端渲染不执行;里面不能更新 state。

一句话概括它的能力边界:只做同步的样式插入,别的一概不做。

官方其实不建议运行时注入#

这一点比 Hook 本身更值得记住。官方对 CSS-in-JS 的建议顺序是:

  1. 用编译器把静态样式抽出成 CSS 文件。
  2. 随状态变化的部分用内联样式。

运行时往 <style> 里插标签,官方明确不推荐:它会让浏览器频繁重算样式,时机不对时还会很慢。useInsertionEffect 只解决了后一半问题,前一半解决不了。

业务代码里该怎么做#

不要在组件里手写 useInsertionEffect 去插样式。业务里有更省事的选择:CSS 文件、CSS Modules、原子化方案,动态的少数字段用内联样式。

真要动态插,useEffect 就够了。业务组件的样式变化不涉及「必须在布局计算之前完成」这条约束。

你会碰它的两种场合#

一是在维护一个 CSS-in-JS 库,需要定注入时机;二是读这类库的源码,认出它在用这个 Hook,也知道它为什么不能用 useEffect 代替。

与另外两个 Effect 的分工#

Hook什么时候跑拿来做什么
useInsertionEffect其他 layout Effect 之前库注入样式
useLayoutEffectDOM 变更之后、绘制之前先量布局再改样式
useEffect绘制之后同步外部系统:订阅、计时器、请求

第 19 篇,共 39 篇本文属于系列

useInsertionEffect
https://www.choria.top/posts/hook-use-insertion-effect/
作者
乔瑞雅·克林威尔
发布于
2026-05-02
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

最后更新于 ,距今已过 190 天

部分内容可能已过时