:::info useLayoutEffect看起来和useEffect非常的相似,事实上他们也只有一点区别而已。
- useEffect会在渲染的内容更新到DOM上之后执行,不会阻塞DOM的更新。
- useLayoutEffect会在渲染的内容更新到DOM上之前执行,会阻塞DOM的更新。
如果我们希望在某些操作发生之后再更新DOM,那么应该将这个操作放到useLayoutEffect这个hook中。
- 相当于vue中的this.$nextTick()函数的使用,在下一次dom更新之前进行调用。
:::
1、案例演示
1、执行的原理问题:我们设置的初始化状态为100,我们的组件进行相应的挂载,执行useEffect hook函数,不满足条件,页面成功的渲染,界面的值为最初的状态10。我们的useEffect hook是对count数据进行了相应的依赖,如果我们的count数据一旦发生变化,那么我们的useEffect函数将会直接执行。 2、界面成功的渲染后,我们对按钮进行点击,将count的值设置为了0,此时我们的页面count应该先显示为0,但是我们的useEffect hook fuction对count状态进行了依赖,count发生了变化,此时的useEffect hook将会执行,进行相应的判断,判断的条件成立,设置了新的count的值,界面也会进行更新。此时count发生了变化useEffect将会再次执行条件不成立。这个函数停止运行。 3、需要解决页面闪烁的问题。
import React, { useState, useEffect } from 'react'
export default function EffectHookDemo() {
// 定义状态和修改状态的行为
const [count, setCount] = useState(10)
// 使用useEffect在组件挂载完毕后执行的hook函数
useEffect(() => {
# 最开始执行了一次,按钮点击之后再执行两次 里面的逻辑原理很重要
// 执行相应的逻辑问题
if(count === 0) {
setCount(Math.random())
}
}, [count])
return (
<div>
<h2>useEffect来修改count的变化</h2>
<h1>{ count }</h1>
<button onClick={ () => setCount(0)}>修改count</button>
</div>
)
}
为了解决上述页面会进行两次的渲染(虽然渲染的时间很短)的问题,我们可以使用useLayoutEffect Hook对上述的代码进行相应的改造,解决页面闪烁的问题。
2、useLayoutEffect的使用
// useLayoutEffect页面DOM更新之前执行 就是需要将操作状态的行为执行完毕后再渲染DOM,简单的理解就是阻塞DOM的渲染。
import React, { useState, useLayoutEffect } from 'react'
export default function EffectHookDemo() {
// 定义状态和修改状态的行为
const [count, setCount] = useState(10)
// 使用useEffect在组件挂载完毕后执行的hook函数
// useEffect(() => {
// if(count === 0) {
// setCount(Math.random())
// }
// }, [count])
// 使用useLayoutEffect hook解决上述的问题 解决页面闪烁的问题
useLayoutEffect(() => {
if(count === 0) {
// 修改状态
setCount(Math.random())
}
}, [count])
return (
<div>
<h2>useEffect来修改count的变化</h2>
<h1>{ count }</h1>
<button onClick={ () => setCount(0)}>修改count</button>
</div>
)
}
3、原理解析
:::info
useLayoutEffect hook的原理解析:
useLayoutEffect看起来和useEffect非常的相似,事实上他们只有一点区别而已:
- useEffect会这渲染的内容更新到DOM上执行,不会阻塞DOM的更新
- useLayoutEffect会再渲染的内容更新到DOM上之前执行,会阻塞DOM的更新
如果我们希望某些操作发生之后再更新DOM,那么可以将这个操作放到useLayoutEffect操作中 :::