跳到主要内容

认识

2023年02月22日
柏拉文
越努力,越幸运

useLayoutEffect 可以让你在函数中使用副作用,执行时机在DOM更新之前。本质上 useInsertionEffect 主要是解决 CSS-in-JS 在渲染中注入样式的性能问题。这个 hooks 主要是应用于这个场景,在其他场景下 React 不期望用这个 hooks 。

背景


CSS-in-JS 的注入会引发哪些问题呢?

首先看部分 CSS-in-JS 的实现原理,拿 Styled-components 为例子,通过styled-components,你可以使用ES6的标签模板字符串语法(Tagged Templates)为需要 styled 的 Component 定义一系列CSS属性,当该组件的JS代码被解析执行的时候,styled-components 会动态生成一个 CSS 选择器,并把对应的 CSS 样式通过 style 标签的形式插入到 head 标签里面。动态生成的 CSS 选择器会有一小段哈希值来保证全局唯一性来避免样式发生冲突。这种模式下本质上是动态生成 style 标签。

如果在 useLayoutEffect 使用 CSS-in-JS 会造成哪里问题呢?

  • 首先 useLayoutEffect 执行的时机 DOM 已经更新完成,布局也已经确定了,剩下的就是交给浏览器绘制就行了。

  • 如果在 useLayoutEffect 动态生成 style 标签,那么会再次影响布局,导致浏览器再次重回和重排。

因此, useInsertionEffect 的作用就出现了,useInsertionEffect 的执行在 DOM 更新前,所以此时使用 CSS-in-JS 避免了浏览器出现再次重回和重排的可能,解决了性能上的问题。

模拟一下在 useInsertionEffect 使用 CSS-in-JS 流程:

export default function Index(){

React.useInsertionEffect(()=>{
/* 动态创建 style 标签插入到 head 中 */
const style = document.createElement('style')
style.innerHTML = `
.css-in-js{
color: red;
font-size: 20px;
}
`
document.head.appendChild(style)
},[])

return <div className="css-in-js" > hello , useInsertionEffect </div>
}