我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

苏南大叔的react教程,本文说一下一个很鸡肋的函数useLayoutEffect。这个函数鸡肋到什么地步呢?连react官方都不建议你使用这个函数,都建议你使用useEffect来代替它。所以,你还想看这个useLayoutEffect函数是怎么回事么?useLayoutEffectuseEffect到底有什么区别呢?

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - uselayouteffect
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-1)

苏南大叔的程序如此灵动博客,记录苏南大叔和计算机代码的故事。测试环境:create-react-app@5.0.1react@18.2.0react-dom@18.2.0node@16.14.2

不推荐使用useLayoutEffect

下面的文字是react官方原话:

注意 useLayoutEffect 与 componentDidMount、componentDidUpdate 的调用阶段是一样的。但是,我们推荐你一开始先用 useEffect,只有当它出问题的时候再尝试使用 useLayoutEffect。

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - 官方不推荐使用uselayouteffect
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-2)

使用方法和useEffect一致

使用方法和useEffect基本一致,连官方都推荐使用useEffect,而不是useLayoutEffect。两者都是以use开头,都是应用于函数组件的hook函数。参考文字:

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - uselayouteffect-code
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-3)

挂载或更新:

useLayoutEffect(() => {
    console.log("挂载或更新,useLayoutEffect");
});

挂载和卸载[]

useLayoutEffect(() => {
    console.log("挂载,useLayoutEffect");
    return () => {
        console.log("卸载,useLayoutEffect");
    }
}, []); 

变量更新[var1,var2]

useLayoutEffect(() => {
    console.log("变量更新,useLayoutEffect");
},[state]);

useLayoutEffect先于useEffect执行

执行顺序:useLayoutEffect => 浏览器渲染 => useEffect;

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - 执行顺序
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-4)

测试代码:

import React, { useEffect, useLayoutEffect, useState, useRef } from "react";
const Sunan = () => {
    const [state, setState] = useState("sunan大叔");
    useEffect(() => {
        console.log("挂载");
        return () => {
            console.log("卸载");
        }
    }, []);
    useEffect(() => {
        console.log("挂载或更新");
    });
    useEffect(() => {
        console.log("变量更新");
    }, [state]);
    useLayoutEffect(() => {
        console.log("挂载,useLayoutEffect");
        return () => {
            console.log("卸载,useLayoutEffect");
        }
    }, []);
    useLayoutEffect(() => {
        console.log("挂载或更新,useLayoutEffect");
    });
    useLayoutEffect(() => {
        console.log("变量更新,useLayoutEffect");
    }, [state]);
    return (
        <div>
            <button onClick={() => { setState("苏南大叔") }}>
                {state}
            </button>
        </div>
    );
};
export default Sunan;

可见所有的useLayoutEffect输出都在useEffect输出之前。但是在这个例子中,并不能定义同为一组的"挂载"/"挂载或更新"/"变量更新"之间的前后顺序。

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - 执行顺序-2
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-5)

大家可以切换同一组中的代码的先后顺序,就会发现:对于同一组内的代码顺序,和代码定义的位置还是有关系的。

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - 内部顺序显示
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-6)

useLayoutEffect同步阻碍渲染,useEffect异步

useLayoutEffectuseEffect,效果上有所差异。差异点是:

  • useLayoutEffect是同步的,就是说在页面上出现dom元素之前,会等待useLayoutEffect的执行。也就是说,react处理的dom结构,在提交给浏览器渲染之前,会等待useLayoutEffect的再处理(也就是说会阻碍页面渲染)。
  • useEffect是异步的,不会阻碍页面渲染,当浏览器已经渲染页面后,才会被执行。

例子如下:

import React, { useEffect, useState } from "react";
const Sunan = () => {
    const [state, setState] = useState("sunan大叔");
    useEffect(() => {
        // console.log("挂载或更新");
        let i = 0;
        while (i <= 500000000) {
            i++;
        };
        setState("------");
    });
    return (
        <div>
            <button onClick={() => { setState("苏南大叔") }}>
                {state}
            </button>
        </div>
    );
};
export default Sunan;

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - useEffect效果
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-7)

在这个例子中,证明是否阻碍页面渲染的证明是:使用useEffect的时候,可以明显看到state的数据变化。而useLayoutEffect则不会看到这个文字的变化过程,因为这个数据在提交给浏览器渲染之前就已经被修改过了。

苏南大叔:react教程,如何用useLayoutEffect?与useEffect有何区别? - uselayouteffect效果
react教程,如何用useLayoutEffect?与useEffect有何区别?(图8-8)

import React, { useLayoutEffect, useState } from "react";
const Sunan = () => {
    const [state, setState] = useState("sunan大叔");
    useLayoutEffect(() => {
        // console.log("挂载或更新");
        let i = 0;
        while (i <= 500000000) {
            i++;
        };
        setState("------");
    });
    return (
        <div>
            <button onClick={() => { setState("苏南大叔") }}>
                {state}
            </button>
        </div>
    );
};
export default Sunan;

结束语

更多react经验文字内容,请参考苏南大叔的文字:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react