初入React——useEffect()和useLayoutEffect()

91 阅读3分钟

前言:这周去简单了解了useEffect()和useLayoutEffect()的使用方式和区别,写下文章,记录学习的历程。

共同点

useEffectuseLayoutEffect的使用方式都是类似的,第一个参数接收一个函数,第二个参数为接收一个数组。如果只传一个空数组,逻辑处理函数里面的逻辑只会执行一次。如果第二个参数是数组,包含多个,useEffect不会执行多遍,而是会异步等待一轮setState更新全部完成、re-render之后才执行。

/*例子中useEffect和useLayoutEffect效果一样,笔者就只用useEffect作为代码贴出来*/
import React,{useState,useEffect, useLayoutEffect,} from "react";
const DrawCom = ()=>{
    const [state,setState] = useState('初始数据')
    const [count,setCount] = useState(0)  
    const [shuju,setShuju] = useState({age:5,a:{b:2}})
    useEffect(() => {
        setState("数据改变了");
        setCount(2)
        setCount(3)
        console.log(state)
        console.log(count)
      },[count,state]);
      useEffect(()=>{
        console.log('shuju',shuju)
      },[shuju])

      function changeObj(){
        setShuju(obj=>{
            /**
             * 例子1
             * 这里的代码会发现控制台打印了最新的值但是视图却一直旧的值
             */
            obj.age+=1
            console.log('obj',obj)
            return obj

            /**
             * 例子2
             * 这里的代码可以做到视图同步更新
             */
            let newObj = {...obj}
            newObj.age+=1
            //newObj.a.b+=1//这里需要注意,拓展运算符拷贝是“一深二浅”,第二层开始就是浅拷贝。所以这里修改是不会触发useEffect的
            return newObj
        })
      }
    return(
        <>
        <p>{state}</p>
        <div>{shuju.age}</div>
        <div>{shuju.a.b}</div>
        <button onClick={()=>changeObj()}>Click</button>
        </>
    )
}

export default DrawCom

补充:上述会有两个小例子,例子1中改变obj指向的值是不会触发useEffectuseLayoutEffect,因为此时改变的是obj对象里面的值,需要改变里面的指向。所以笔者在例子2中使用了进行拓展运算符进行深拷贝一份,改变其指向地址,才会触发监听。

不同点

我们先来个小demo思考下

import React,{useState,useEffect, useLayoutEffect,} from "react";

const DrawCom = ()=>{
    const [state,setState] = useState('初始数据')
    useEffect(() => {
        let i = 0;
        while(i <= 1000000000) {
          i++;
        };
        setState("数据改变了");
        console.log('组件渲染了')
      },[]);
    //   useLayoutEffect(()=>{
    //     let i = 0;
    //     while(i <= 1000000000) {
    //       i++;
    //     };
    //     setState("数据改变了");
    //   },[])
    return(
        <>
        <p>{state}</p>
        </>
    )
}

export default DrawCom

第一次我们使用useEffect会发现,页面会先展示‘数据展示’,然后闪烁一下,变为‘数据改变了’。第二次我们将useEffect注释掉,换为useLayoutEffect,发现没有闪烁的行为,数据直接就是修改后的。这就是因为useEffect异步执行的,而useLayoutEffect同步执行的。

 useEffect 的函数会在浏览器完成布局与绘制之后,在一个延迟事件中被调用。react渲染组件不必等待useEffect函数执行完毕,造成阻塞。

useLayoutEffect会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。(有可能会阻塞dom渲染)useLayoutEffect 与 componentDidMountcomponentDidUpdate 的调用阶段是一样的。

官网推荐我们推荐一开始先用 useEffect,只有当它出问题的时候再尝试使用 useLayoutEffect。百分之99的情况,使用useEffect就可以了,可能需要用到useLayoutEffect的情况就是,在使用useEffect的情况下,我们的屏幕会出现闪烁的情况(组件在很短的时间内渲染了两次)。

总结:useEffectuseLayoutEffect两个Hook还是比较容易使用,技术水平有限,能分享的暂时就这些。如有写得不妥之处,请各位大佬不吝赐教(* ̄︶ ̄)