useEffect和useLayoutEffect有什么区别?

Posted 前端e站

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了useEffect和useLayoutEffect有什么区别?相关的知识,希望对你有一定的参考价值。

上一节我们介绍了useRef 保存引用值和useImperativeHandle 透传 Ref,这一节之后整个React hooks的学习就告一段落了。

useLayoutEffect 同步执行副作用

大部分情况下,使用 useEffect 就可以帮我们处理组件的副作用,但是如果想要同步调用一些副作用,比如对 DOM 的操作,就需要使用 useLayoutEffect,useLayoutEffect 中的副作用会在 DOM 更新之后同步执行。

function App() 
  const [width, setWidth] = useState(0);
  useLayoutEffect(() => 
    const title = document.querySelector("#title");
    const titleWidth = title.getBoundingClientRect().width;
    console.log("useLayoutEffect");
    if (width !== titleWidth) 
      setWidth(titleWidth);
    
  );
  useEffect(() => 
    console.log("useEffect");
  );
  return (
    <div>
      <h1 id="title">hello</h1>
      <h2>width</h2>
    </div>
  );

在上面的例子中,useLayoutEffect 会在 render,DOM 更新之后同步触发函数,会优于 useEffect 异步触发函数。

useEffect和useLayoutEffect有什么区别?

简单来说就是调用时机不同,useLayoutEffect和原来componentDidMount&componentDidUpdate一致,在react完成DOM更新后马上同步调用的代码,会阻塞页面渲染。而useEffect是会在整个页面渲染完才会调用的代码。

官方建议优先使用useEffect

在实际使用时如果想避免页面抖动(在useEffect里修改DOM很有可能出现)的话,可以把需要操作DOM的代码放在useLayoutEffect里。关于使用useEffect导致页面抖动,参考git仓库git仓库示例。

不过useLayoutEffect在服务端渲染时会出现一个warning,要消除的话得用useEffect代替或者推迟渲染时机。

React Hooks 不足

尽管我们通过上面的例子看到 React Hooks 的强大之处,似乎类组件完全都可以使用 React Hooks 重写。但是当下 v16.8 的版本中,还无法实现 getSnapshotBeforeUpdate 和 componentDidCatch 这两个在类组件中的生命周期函数。官方也计划在不久的将来在 React Hooks 进行实现。

父组件

import Child from 'component/Child'
 
 const dataobj = 
     pdata1: 1,
     pdate2:2

 const [dataobj ,setDataobj ] = useState();
 const pchildref = useRef();
 function parantHandler() 
    // 子组件调用的父组件方法

 function parentDivClick() 
    // 父组件调用子组件方法
    pchildref .current._childFn();

 return (
    <div>
        <Child
             ref=pchildref
             params1=dataobj.pdata1
             params2=dataobj.pdata2
             handlerClick=parantHandler>
        </Child>
        <div onClick=parentDivClick></div>
    </div>
)

子组件

const Child = (props,ref) =>   
    // 接收父组件的传值
     const  params1,params2,handlerClick = props;
     const childRef = useRef();
    // 暴露的子组件方法,给父组件调用
    useImperativeHandle(ref,() => 
         return 
            _childFn() 
                // something….
            
        
    )
    // handlerClick子组件调用父组件方法
     return <div
        ref=childRef onClick=handlerClick>
        </div>

// forwardRef 配合useRef 父组件调用子组件方法使用
export default forwardRef(Child);

关注我,一起学习更多的前端技术。

 

以上是关于useEffect和useLayoutEffect有什么区别?的主要内容,如果未能解决你的问题,请参考以下文章

反应 useEffect 和 useRef

useState和useEffect

关于 React.useEffect() 和 React.useState() 的问题

反应 useEffect 和 setInterval

如何循环使用 useEffect 和 setState

useEffect() 和 Google Firebase onAuthStateChange