认识
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>
}