深入了解 useLayoutEffect

这篇具有很好参考价值的文章主要介绍了深入了解 useLayoutEffect。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

深入了解 useLayoutEffect

近年来,React 已经在不断变化的 Web 开发领域巩固了自己的地位,成为构建高性能和交互式用户界面的最有效方法之一。随着 Hooks 新特性的引入,React 彻底改变了开发人员在函数组件中管理有状态和可重用逻辑的方式。

有了 Hooks,你可以在不需要编写 ES6 类组件的同时使用状态和其他 React 特性。其中一个重要的 hook 是useLayoutEffect,它允许开发人员在 React 组件中处理和执行副作用。

在本文中,我们将深入探索useLayoutEffecthook、它与 useEffect 的不同之处,并学习如何正确地利用其功能来增强用户体验。

React 中有哪些副作用?

要真正掌握useLayoutEffect是什么以及它的作用,有必要对 React 中的副作用有一个扎实的理解。

组件的主要职责包括渲染用户界面(UI)、响应用户输入和事件,以及在必要时重新渲染 UI。在处理一个不属于组件渲染周期的 React 项目时,你可能需要执行一些任务或操作。这些被称为“副作用”。

副作用是应用程序中发生的与 UI 渲染不相关(至少不直接)的任何事情。例如,向服务器发送 HTTP 请求、在浏览器内存中存储数据、设置时间函数等。在这些场景中没有 UI 更改。换句话说,React 不会为这些场景重新渲染你的组件。

虽然它们在我们的应用程序中非常有用,并且是函数式编程中的一个关键概念,但副作用也很难管理,如果处理不当,可能会导致意想不到的行为和性能问题。

要处理副作用,你可以使用一组称为 Effect hooks 的内置钩子,即:useEffectuseLayoutEffectuseInsertionEffect

在这些钩子中,与其他钩子相比,useEffect 是 react 开发人员使用最多的钩子。但问题来了。它适用于各种副作用吗?

useEffect

如果你使用类组件编写过 React 代码,那么你应该熟悉生命周期方法:componentDidMountcomponentDidUpdatecomponentWillUnmount

useEffect 钩子是所有三个生命周期方法的组合,因此它允许我们在函数组件中访问生命周期方法。useEffect钩子是异步运行的,通常用于发出 API 请求。

下面是一个使用栗子:

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
		// 副作用逻辑在这里
    console.log('Component rendered!');
		// 清理函数(可选)
    return () => {
      console.log('Component unmounted!');
    };
  }, []); // 空依赖数组,只在挂载时运行
  return (
    <div>
      {/* Component JSX */}
    </div>
  );
}

useEffect 在组件最初完全加载后运行,然后每次组件状态发生变化时运行。

useEffect 有什么问题?

如上所述,useEffect 挂钩是异步的,这有一个明显的缺点,即它只能在组件挂载后调用。这意味着依赖于组件布局的副作用不能使用 useEffect 执行。

现在我们如何解决这个问题,这就是 useLayoutEffect 的用武之地。

useLayoutEffect

虽然许多 React 开发人员都熟悉使用的 useEffect hook,但 useLayoutEffect hook 与之比起来还是有点黯然失色,但仍然是提高 React 应用程序性能的强大工具。

useEffect hook 不同,useLayoutEffect hook 是同步运行的,这意味着它会在 React 执行完所有必要的 DOM 变更后立即运行,但恰好在浏览器绘制屏幕之前运行。它具有与 useEffect hook 相同的 API 和相似的语法。引入此 hook 是为了解决一些在使用 useEffect hook 时困扰开发人员的布局的特殊问题。

下面是一个使用栗子:

import React, { useLayoutEffect } from 'react';

function MyComponent() {
  useLayoutEffect(() => {
		// 在这里执行副作用
		// 此代码在组件渲染之后但在浏览器绘制屏幕之前运行
    
    return () => {
			// 清理代码在这里(可选)
    };
  }, []);

  return (
		// 组件的 JSX 代码
  );
}

useLayoutEffect 通常与 useRef hook 一起使用,如此你可以获得对可用于读取布局信息的任何 DOM 元素的引用。

useLayoutEffect 是如何运行的?

以下是 useLayoutEffect hook 如何运行的基本概述:

  • 用户与应用程序交互。
  • 组件的状态发生变化。
  • 之后,DOM 被更改。
  • 如果 useLayoutEffect 依赖项已更改,则调用此方法以清除先前渲染的效果。
  • 清理后,调用 useLayoutEffect hook。
  • 更改会反映在浏览器屏幕上。

什么时候应该使用 useLayoutEffect?

1. 添加平滑滚动

import React, { useRef, useLayoutEffect } from 'react';

const SmoothScrolling = () => {
  const containerRef = useRef(null);

  useLayoutEffect(() => {
    const container = containerRef.current;

    const handleScroll = () => {
			// 平滑滚动到容器顶部
      container.scrollTo({
        top: 0,
        behavior: 'smooth',
      });
    };

		// 当组件被挂载时滚动到顶部
    handleScroll();

		// 添加事件侦听器以在后续滚动时滚动到顶部
    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return (
    <div ref={containerRef}>
      {/* 你的内容 */}
    </div>
  );
};

在上面的代码中,useLayoutEffect hook 用于向容器元素添加平滑滚动功能。设置事件侦听器以侦听窗口对象上的滚动事件并调用 handlescroll 函数。该函数将使用带有 { top: 0, behavior: 'smooth' } 作为参数的 scrollTo 方法将容器平滑地滚动到顶部。

useLayoutEffect 将在挂载组件时执行初始滚动到顶部。添加了清理功能以在卸载组件时删除事件侦听器。

2. 动画元素

import React, { useRef, useLayoutEffect } from 'react';

const AnimatingElements = () => {
  const elementRef = useRef(null);

  useLayoutEffect(() => {
    const element = elementRef.current;

		// 在挂载时为元素的不透明度设置动画
    element.style.opacity = 0;
    setTimeout(() => {
      element.style.opacity = 1;
    }, 1000);

    return () => {
			// 组件卸载时清理动画
      element.style.opacity = 0;
    };
  }, []);

  return <div ref={elementRef}>Animate me!</div>;
};

上面的代码块演示了如何使用 useLayoutEffect 为元素的不透明度设置动画。元素的初始不透明度设置为 0,然后使用 setTimeout 函数在 1000 毫秒的延迟后将其设置为 1。然后 useLayoutEffect 在组件挂载后应用动画。当组件被卸载时,元素的不透明度重置为 0。

3. 自动对焦输入框

import React, { useRef, useLayoutEffect } from 'react';

const AutoFocusInput = () => {
  const inputRef = useRef(null);

  useLayoutEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} />;
};

在前面的代码中,我们使用 useLayoutEffect 在组件挂载时自动聚焦到输入字段。我们继续使用 ref 访问输入元素。在 useLayoutEffect 中,我们调用输入元素上的 focus 方法来赋予它焦点。因为我们希望它只运行一次,所以我们将依赖项数组留空 ([])。注意:对于此示例,没有清理功能,因为在卸载组件时不需要撤消焦点。

比较 useEffect 和 useLayoutEffect

useEffect Hook useLayoutEffect Hook
执行顺序 在渲染并应用任何更新后运行 在渲染之后但在浏览器绘制屏幕之前运行
执行机制 异步执行 同步执行
执行时机 在渲染阶段异步执行 在提交阶段同步执行
使用场景 获取数据,订阅事件,执行副作用 执行测量,根据布局同步修改 DOM
性能 无阻塞,不延迟渲染,在大多数情况下针对性能进行了优化 可能阻塞,可能会延迟渲染,如果不小心使用,可能会导致性能问题
使用注意事项 对于大多数副作用和不需要立即视觉更新的效果,更可取。 适用于需要在浏览器绘制之前同步应用的效果
服务器端渲染 (SSR) 可在客户端和服务器端渲染环境中使用。 不建议用于服务器端渲染,因为它可能会阻塞渲染,请改用:useEffect

使用 useLayoutEffect 的好处

  • 它确保布局在整个过程中非常一致,并且在用户看到之前是稳定的。
  • 它通过将状态更改与 DOM 更改同步来帮助防止不必要的重新渲染或重新绘制。
  • 防止闪烁或不需要的内容闪烁:在某些情况下,使用 useLayoutEffect 可以帮助消除当元素需要根据布局信息重新定位或设置样式时可能发生的视觉闪烁或布局偏移。通过在浏览器绘制之前同步执行适当的布局更改,你可以防止在使用 useEffect 并且在布局更改和渲染之间有延迟时可能出现的视觉故障。

使用 useLayoutEffect 的陷阱

  • 根据 React 官方文档,这个 hook 的一个主要缺陷是它会损害应用程序的性能。
  • 不支持服务器端渲染 (SSR):由于 SSR 需要异步呈现以避免阻塞服务器线程,因此在 SSR 设置中使用 useLayoutEffect 可能会导致服务器渲染的内容和客户端渲染的内容不匹配。

使用 useLayoutEffect 的最佳实践

在 React 中使用 useLayoutEffect hook 时,遵循最佳实践以确保你的代码正确高效地运行。以下是有效使用 useLayoutEffect 的一些推荐做法:

  • useLayoutEffect 是一个 Hook,因此必须在组件的顶层调用。
  • 不要在循环或条件内调用它。如果你需要这样做,请提取一个组件并将效果移到那里。
  • 仅将 useLayoutEffect hook 用于依赖于组件布局的副作用。
  • 可以使用 ref 对象来访问组件的当前布局。
  • 避免使用 useLayoutEffect 来更新组件的状态。
  • 避免执行可能会导致渲染延迟的昂贵操作和计算。
  • 始终考虑使用替代方法,例如 useEffect
  • 限制 useLayoutEffect 的使用:在大多数情况下,useEffect 足以提供所需的功能。 useLayoutEffect 仅在需要同步执行和快速访问 DOM 的情况下使用。
  • 注意依赖关系:就像 useEffect 一样,useLayoutEffect 钩子也接受一个依赖关系数组作为第二个参数。因此,请确保包含所有相关依赖项以避免不必要的重新渲染。

小结

在本文中,你已经了解了很多有关 useLayoutEffect hook、相同点和不同点、最佳实践等的知识。到现在为止,我相信你已经了解了足够多的知识,可以在你的应用程序中正确使用它来改善整体体验并解决重大问题。文章来源地址https://www.toymoban.com/news/detail-496929.html

到了这里,关于深入了解 useLayoutEffect的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入了解Docker镜像操作

    Docker是一种流行的容器化平台,它允许开发者将应用程序及其依赖项打包成容器,以便在不同环境中轻松部署和运行。在Docker中,镜像是构建容器的基础,有些家人们可能在服务器上对docker镜像的操作命令不是很熟悉,本文将深入探讨Docker镜像的操作。 什么是Docker镜像? D

    2024年02月10日
    浏览(38)
  • 网络协议的深入了解!

    随着互联网的普及和发展,网络协议在计算机网络中扮演着至关重要的角色。网络协议是计算机网络中不同设备之间进行通信和数据交换的规则和标准。本文将对网络协议的概念、分类以及一些常见的网络协议进行详细的介绍和案例分析。 网络协议是一种规范,它定义了计算

    2024年02月04日
    浏览(33)
  • 深入了解 PostgreSQL 扩展插件

    在 PostgreSQL 数据库中,扩展插件是极具价值的工具,它们为我们提供了丰富多样的功能增强。本篇博客将深入介绍几个常用的 PostgreSQL 扩展插件,包括 pg_stat_statements、uuid、postgis 以及 postgis_raster。这些插件不仅能够优化数据库性能,还能处理地理信息数据,为数据管理与利用

    2024年02月14日
    浏览(35)
  • 深入了解百度爬虫工作原理

    在当今数字化时代,互联网已经成为人们获取信息的主要渠道之一。而搜索引擎作为互联网上最重要的工具之一,扮演着连接用户与海量信息的桥梁角色。然而,我们是否曾经好奇过当我们在搜索引擎中输入并点击搜索按钮后,究竟是如何能够迅速地找到相关结果呢?

    2024年02月05日
    浏览(49)
  • 深入了解Maven(一)

    目录 一.Maven介绍与功能 二.依赖管理 1.依赖的配置 2.依赖的传递性 3.排除依赖 4.依赖的作用范围 5.依赖的生命周期 maven是一个项目管理和构建工具,是基于对象模型POM实现。 Maven的作用: 便捷的依赖管理:使用Maven可以简化依赖管理过程。通过在项目的pom.xml文件中声明依赖关

    2024年02月12日
    浏览(28)
  • 一文深入了解Cmk

    定义:Cmk是德国汽车行业常采用的参数,是\\\"Machine Capability Index\\\" 的缩写,称为临界机器能力指数,它仅考虑设备本身的影响,同时考虑分布的平均值与规范中心值的偏移。由于仅考虑设备本身的影响,因此在采样时对其他因素要严加控制,尽量避免其他因素的干扰,计算公式

    2024年02月15日
    浏览(33)
  • 深入了解 Linux 信号

    目录 一、什么是 Linux 信号 1.1 信号的定义和作用 1.2 信号的分类和编号 二、Linux 信号的发送和接收 2.1 发送信号的方法 2.2 接收信号的方法 2.3 信号的处理方式 三、信号的处理函数 3.1 信号的默认处理函数 3.2 注册信号处理函数 3.3 信号处理函数的编写技巧 四、信号的处理机制

    2024年02月03日
    浏览(28)
  • 带你深入了解多态——C++

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 、 Linu

    2024年02月08日
    浏览(48)
  • c语言指针(深入了解指针)

    前沿:       有人曾说过不会指针等于没有学习c语言,而我也是非常认同这个观点的,要想学习好c语言,指针是比不可缺少的,如果指针学不会c语言也就没办法学好,而向如此越重要的东西越比较难学,但难学并不代表学不会,这片文章将由简单到复杂让你深刻的了解指针

    2023年04月08日
    浏览(48)
  • 深入了解图片Base64编码

    title: 深入了解图片Base64编码 date: 2024/4/8 10:03:22 updated: 2024/4/8 10:03:22 tags: Base64编码 图片转换 HTTP请求 前端开发 移动应用 性能优化 图片压缩 Base64编码是一种将二进制数据转换为文本字符串的编码方式,通过将数据转换为一种可打印的ASCII字符集,以便在文本协议中传输。对图

    2024年04月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包