Code前端首页关于Code前端联系我们

介绍下React中useLayoutEffect钩子的使用场景

terry 1个月前 (03-19) 阅读数 114 #React
文章标签 React

今天来分享下React中useLayoutEffect钩子的使用场景。

钩子的加入不仅意味着功能组件将能够提供自己的状态,而且还能通过引入useEffect钩子来管理自己的生命周期事件。

此外,这次更新还引入了一个全新的useLayoutEffect钩子,根据React文档,它的作用与[useEffect]钩子的作用相当相似;所以这就引出了一个问题。 两者之间到底有什么区别?

如果你对钩子还不熟悉,我建议你去看看 这篇文章在那里你会很好地了解它们是什么,它们的用途,以及你如何在你的应用程序中使用它们。

在这篇文章中,我们将更深入地探讨每个钩子的作用,两者之间的区别是什么,到最后,你应该对它们各自的工作原理有更好的理解,什么时候应该使用其中一个而不是另一个,以及爱上其中一个的一些常见陷阱。

useEffect钩子的概述

这个钩子最初是作为处理功能组件中的副作用的另一种方式添加的,类似于基于类的组件中的componentDidMount和componentDidUpdate方法(它们也是在同一时间运行的)。

因此,它在基于类的组件中的等价物是componentDidMount、componentDidUpdate 和 componentWillUnmount方法的组合,后者是作为参数传递给钩子的回调语句中的一个效果。

钩子流程

  • 你以某种方式引起渲染(状态被更新或父类重新渲染)。

  • React渲染你的组件(调用它)

  • 屏幕得到视觉上的更新

  • 然后运行useEffect

useLayoutEffect钩子的概述

与useEffect类似,它与Class Components中的componentDidMount和componentDidUpdate同时运行。然而,useLayoutEffect是同步运行的,与useEffect相反,这意味着它收到的回调只有在组件中进行了V-DOM计算之后,但在它们被绘制到实际的DOM之前才会被调用。

这意味着,如果我们确实需要对任何DOM元素进行任何JavaScript查询,useLayoutEffect是我们可能需要的钩子。

钩子流程

  • 你以某种方式导致渲染(改变状态,或者父类重新渲染)。

  • React渲染你的组件(调用它)

  • useLayoutEffect运行,React等待它完成。

  • 屏幕在视觉上被更新

什么时候使用useLayoutEffect钩子?

在使用useEffect钩子时,有一个常见的问题,即当一个组件的状态被更新时,它可能会 "闪动"。这是因为组件在继续进行异步计算的过程中,首先会以部分就绪的状态进行渲染,然后才会以最终的状态进行重新渲染。

这是一个很好的指示,你可能想使用useLayoutEffect钩子来代替。

这样的例子是试图在点击一个按钮时生成并渲染一个极高的数值,就像这个例子中一样:

import { useState, useEffect } from 'react';
import './App.css';
function App() {
  const [value, setValue] = useState(0);
  useEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);
  console.log('render', value);
  return (
    <div className="App">
      <p>Value: {value}</p>
      <button onClick={() => setValue(0)}>
        Generate Random Value
      </button>
    </div>
  );
}
export default App;

如果我们要检查我们的应用程序是如何表现的,我们将看到每次我们按下按钮时一个不断变化的闪烁的数字。

状态更新时闪烁的组件

如果我们使用useLayoutEffect钩子,我们就可以摆脱这个视觉错误。

import { useState, useLayoutEffect } from 'react';
import './App.css';
function App() {
  const [value, setValue] = useState(0);
  useLayoutEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);
  console.log('render', value);
  return (
    <div className="App">
      <p>Value: {value}</p>
      <button onClick={() => setValue(0)}>
        Generate Random Value
      </button>
    </div>
  );
}
export default App;

而且,你可以从最后一个视频样本中看到,我们已经能够摆脱闪烁的效果了。

这是因为这两个钩子的行为略有不同;第一个钩子是异步处理计算和DOM渲染的,而后者是先进行计算,然后才处理计算结果在屏幕上的渲染。

在我们的例子中,这意味着useEffect钩子正试图生成随机值,并同时将其渲染到屏幕上。另一方面,useLayoutEffect钩子试图首先完成计算,然后才向我们展示生成的数字。

总结

正如你所注意到的,useLayoutEffect钩子为我们提供了一个干净的解决方案,以解决我们可能发现自己经常与之斗争的问题,那就是被React同时处理DOM绘制和计算的方式所纠缠。

作为一个启示,当你在处理 ref 值或需要做任何类型的工作,围绕着通过vanilla JavaScript方法(如querySelector、querySelectorAll或任何其他方式)查询DOM元素时,你可能想使用useLayoutEffect钩。

请记住,尽管useLayoutEffect钩子为我们提供了很多有用的东西,但在99%的情况下,你最好还是使用useEffect钩子,因为它由于其异步的性质,常常会有更高的性能。

所以,就这样了。

希望你现在已经对这两个钩子的用法有了更好的理解,以及每个钩子可能派上用场的场景;这也是特别常见的,因为它被使用得相当少,要么是由于开发者不知道它,要么是知道它,但不确定它的具体作用。


版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门