自学内容网 自学内容网

react hooks--useLayoutEffect

概述

useLayoutEffect看起来和useEffect非常的相似,事实上他们也只有一点区别而已:

 useEffect会在渲染的内容更新到DOM上后执行,不会阻塞DOM的更新;

 useLayoutEffect会在渲染的内容更新到DOM上之前执行,会阻塞DOM的更新;

官方更推荐使用useEffect而不是useLayoutEffect。

如果我们希望在某些操作发生之后再更新DOM,那么应该将这个操作放到useLayoutEffect。

 

useLayoutEffect 的同步执行

useLayoutEffect 这个 hook 在执行的时候,也是先调用 destroy(),再执行 create()。和 useEffect 不同的是前者在 mutation 阶段执行,后者在 layout 阶段执行。与 useEffect 不同的是,它不用数组去存储销毁和创建函数,而是直接操作 fiber.updateQueue。

卸载上一次的 effect,发生在 mutation 阶段:

执行本次的 effect 创建,发生在 layout 阶段:

useEffect和useLayoutEffect作为组件的副作用,本质上是一样的。共用一套结构来存储effect链表。整体流程上都是先在render阶段,生成effect,并将它们拼接成链表,存到fiber.updateQueue上,最终带到commit阶段被处理。他们彼此的区别只是最终的执行时机不同,一个异步一个同步,这使得useEffect不会阻塞渲染,而useLayoutEffect会阻塞渲染。

演示示例

import React, { memo, useEffect, useLayoutEffect, useState } from 'react'

const App = memo(() => {
  const [count, setCount] = useState(100)

  // useEffect(() => {
  //   console.log('useEffect执行了');
  //   // 这里的执行逻辑就是先赋值为0执行一遍,再设置值重新又执行一遍,就会出现闪烁的现象
  //   if(count === 0){
  //     setCount(Math.random() + 99)
  //   }
  // })

  useLayoutEffect(() => {
    console.log('useLayoutEffect执行了');
    // 这里就不会出现闪烁现象且执行一次
    if(count === 0){
      setCount(Math.random() + 99)
    }
  })

  return (
    <div>
      <h4>count: {count}</h4>
      <button onClick={e => setCount(0)}>设置为0</button>
    </div>
  )
})

export default App

总结

与 useEffect 的用法完全一样,作用也基本相同,唯一的不同在于执行时机,它会在所有的 DOM 变更之后同步调用 effect, 可以使用它来 useEffect 不会阻塞浏览器的绘制任务,它会在页面更新之后才执行。 而 useLayoutEffect 跟 componentDidMount 和 componentDidUpdate 的执行时机一样,会阻塞页面渲染,如果当中有耗时 任务的话,页面就会卡顿。大多数情况下 useEffect 比 class 的生命周期函数性能更好,我们应该优先使用它。 如果你正在将代码从 class 组件迁移到使用 Hook 的函数组件,则需要注意 useLayoutEffect与 componentDidMount、componentDidUpdate 的调用阶段是一样的。但是,我们推荐你一开始先用 useEffect,只有当它出问题的时候再尝试使用 useLayoutEffect。


原文地址:https://blog.csdn.net/weixin_43285360/article/details/142309139

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!