React中useLayoutEffect和useEffect的区别

重点: 1.二者函数签名相同,调用方式是一致的

   2. 怎么简单进行选择: 无脑选择useEffect,除非运行效果和你预期的不一致再试试useLayoutEffect

区别详解:
useEffect是异步执行,而且是在渲染被绘制到屏幕之后执行。
流程如下:
你以某种方式触发了rerender(改变state,或者父组件发生rerender)
React渲染你的组件(调用组件函数)
屏幕在视觉上更新(真实dom操作)
然后useEffect运行

useLayoutEffect是同步执行,时机在渲染之后但在屏幕更新之前。

流程如下:
你以某种方式触发了rerender(改变state,或者父组件发生rerender)
React渲染你的组件(调用组件函数)
useLayoutEffect运行,React等待它完成
屏幕在视觉上更新(真实dom操作)

代码实战

const BlinkyRender = () => {
  const [value, setValue] = useState(0);

  useLayoutEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);

  console.log('render', value);

  return (
    <div onClick={() => setValue(0)}>
      value: {value}
    </div>
  );
};


当点击div时,状态立即改变(value重置为0),这将重新Render组件,然后运行Effect——将值设置为某个随机数,并再次重新Render。


也就是是两次Rerender会快速连续发生。分别换用useLayoutEffect和useEffect观察有什么不同。

你会发现useLayoutEffect的版本会在组件render两次的情况下仅在视觉上更新一次。而useEffect版本在视觉上也会呈现两次,所以会看到闪烁,从0闪烁变成对应的随机数。

 

所以到底什么时候使用useLayoutEffect呢?

如果你的组件在状态更新时闪烁,比如它首先以部分就绪状态呈现,然后立即以最终状态重新呈现——这是一个很好的线索,是时候换useLayoutEffect了。

当您的更新是两步(或多步)过程时,就会出现这种情况。你想在重新绘制屏幕之前一起批处理多个更新吗,试试useLayoutEffect。

 

在大多数情况下,你的effect函数会在对应的依赖项如state或props改变时执行,而对应的回调逻辑往往不会立即影响或根本不影响页面视觉。
比如发一个ajax请求
或者你设置一个了事件处理器


大多数时候,使用useEffect是正确的。如果您的代码导致闪烁,切换到useLayoutEffect,看看是否有帮助。


因为useLayoutEffect是同步的,也就是阻塞的,在你的effect运行完之前,视觉不会更新。如果你的effect中有计算密集型代码,它可能会导致性能体验问题,比如卡顿。大多数effect在运行时并不需要"stop the world",普通的 useEffect几乎可以满足我们所有的需求。

 

posted @ 2020-11-04 19:18  flamestudio  阅读(1076)  评论(0编辑  收藏  举报