ReactReact

useLayoutEffect

2021-12-08  本文已影响0人  就问你怕不怕

useLayoutEffect与useEffect名字很像,用法也大致类似,但两者执行时机不同:

useEffect 的函数会在组件渲染到屏幕之后执行
useLayoutEffect则是在DOM结构更新后、渲染前执行,相当于有一个防抖效果

根据上述特性,可以预计到如果在useEffect中瞬时连续更新某个状态,那么页面会发生多次渲染,现在举例测试。

import { useState, useEffect, useLayoutEffect } from "react";
import * as ReactDOM from "react-dom";

function App() {
  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>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这个测试的意思是,在点击div的时候将value设为0,但在useEffect中又将其设为一个随机值。这样相当于value这个状态快速连续的变更了两次。其表现结果为


微信截图_20211207155835.png

可以看到这里打印出了两个结果,也就是value连续变更了两次,在实际观察页面的时候,这个div是有闪动的,这在交互上和性能上是绝对需要避免的。这个例子中组件的变化顺序是:

  1. click setState (value)
  2. 虚拟 DOM 设置到真实 DOM 上
  3. 渲染
  4. 执行useEffect回调
  5. setState(value)
  6. 虚拟 DOM 设置到真实 DOM 上
  7. 渲染

一共执行了两次渲染:3和7

再看useLayoutEffect的表现:

import { useState, useEffect, useLayoutEffect } from "react";
import * as ReactDOM from "react-dom";

function App() {
  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>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
微信截图_20211207160823.png

这里的打印结果和上面一样,但页面表现却不一样,页面并没有出现闪动,而是正常渲染。

这个例子中组件的变化顺序是:

  1. click setState (value)
  2. 虚拟 DOM 设置到真实 DOM 上
  3. 执行useLayEffect回调
  4. setState (value)
  5. 虚拟 DOM 设置到真实 DOM 上
  6. 渲染

只会进行一次页面渲染

以上,照此看useLayoutEffect比useEffect更好,那么是否可以全部使用前者来代替后者呢?

但官网提到的一些应该注意的点:

  1. 应先使用useEffect,若出问题再尝试useLayoutEffect;
  2. useLayoutEffect与componentDidMount,componentDidUpdate的调用阶段是一样的;
  3. 针对服务端渲染:useEffect和useLayoutEffect都无法在JS代码加载完成之前执行。(笔者暂未接触服务端渲染,不清楚这意味着什么)

详细的关于useEffect和useLayoutEffect执行时机见这篇:深入理解 React useLayoutEffect 和 useEffect 的执行时机

上一篇 下一篇

猜你喜欢

热点阅读