useEffect和useLayoutEffect对比

useEffect

回调在react渲染组件之后执行,并且确保回调不会阻止浏览器绘制(异步的)
执行过程是这样的:

  1. 触发了一个导致重新渲染的操作(改变state、props改变)
  2. react重新渲染组件(调用)
  3. 屏幕可以看到更新
  4. useEffect的回调执行

useLayoutEffect

在react渲染组件之后同步执行
执行过程是这样的:

  1. 触发了一个导致重新渲染的操作(改变state、props改变)
  2. react重新渲染组件(调用)
  3. useLayoutEffect回调函数执行
  4. 屏幕看到更新

代码示例

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

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

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

  console.log("render", value);

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

ReactDOM.render(
  <BlinkyRender />,
  document.querySelector("#root")
);
复制代码

上面这样的代码,点击div,有可能导致页面更新两次(闪烁),使用useLayoutEffect就不会了
useEffect执行过程:

  1. 点击div
  2. state改变,导致react组件重新执行
  3. 屏幕更新
  4. useEffect执行,state再次改变
  5. react组件重新执行,屏幕更新

useLayoutEffect执行过程:

  1. 点击div
  2. state改变,react组件重新执行
  3. useLayoutEffect,state改变
  4. react组件再次执行更新
  5. 屏幕更新

总结

  • useLayoutEffect是同步的,在回调执行后才会浏览器才会更新,如果回调执行时间过长,就会导致画面迟迟不能更新,大部分情况使用useEffect
  • 如果发现了屏幕闪烁的问题,请尝试下useLayoutEffect

参考文章:daveceddia.com/useeffect-v…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享