深入了解 useLayoutEffect

news/2024/11/25 4:23:30/

深入了解 useLayoutEffect

  • 深入了解 useLayoutEffect
    • React 中有哪些副作用?
    • useEffect
    • useEffect 有什么问题?
    • useLayoutEffect
    • useLayoutEffect 是如何运行的?
    • 什么时候应该使用 useLayoutEffect?
      • 1. 添加平滑滚动
      • 2. 动画元素
      • 3. 自动对焦输入框
    • 比较 useEffect 和 useLayoutEffect
    • 使用 useLayoutEffect 的好处
    • 使用 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、相同点和不同点、最佳实践等的知识。到现在为止,我相信你已经了解了足够多的知识,可以在你的应用程序中正确使用它来改善整体体验并解决重大问题。


http://www.ppmy.cn/news/515320.html

相关文章

MERCURY无线面板式AP-强电供电-WiFi密码-IP地址

MERCURY无线面板式AP&#xff0c;WIFI密码&#xff0c;office_2.4GHz&#xff1a;12345678&#xff0c;Guest_2.4GHz&#xff1a;无密码 管理页IP地址(参考)&#xff1a;192.168.1.253&#xff0c;192.168.1.254&#xff0c;melogin.cn

为Debian解决Mercury MW150US无线网卡驱动

layout: post title: “为Debian搞定Mercury MW150US无线网卡驱动” categories: [实施工程] tags: [Linux] 为Debian搞定Mercury MW150US无线网卡驱动 买无线网卡前没认真研究Linux兼容性的问题&#xff0c;看着水星的mini无线网卡小巧便捷就买回来了。狗哥了一下才发现Linux…

水星mercury无线扩展器设置

请先把水星MW300RE 300M扩展器插在电源插座上&#xff0c;然后让电脑搜索连接到扩展器的无线信号&#xff0c;默认的信号名称是&#xff1a;MERCURY_RE_XXXX。其中的XXXX表示这台扩展器MAC地址的后四位&#xff0c;可以在扩展器壳体标签上查看MAC地址&#xff0c;默认无线信号&…

mercury已断开服务器无响应,Mercury使用指南,帮助解决无线网卡运行失败的问题...

为了给更多的电脑用户带来方便&#xff0c;现在很多电脑都是采用无线网络&#xff0c;以笔记本尤为明显。使用无线网络前&#xff0c;往往也需要将无线网卡驱动安装设置好。例如水星品牌的电脑用户想要正常使用无线网络&#xff0c;都必须要安装 mercury 无线网卡驱动 。那么 m…

SQL Server数据库mdf文件中了勒索病毒 mercury。扩展名变为 mercury

2019-01-24 15:57:27 SQL&#xff0c;数据库&#xff0c;勒索病毒&#xff0c;mdf文件中毒&#xff0c;mercury *SQL Server数据库mdf文件中了勒索病毒.mdf.mercury。mercury SQL Server数据库mdf文件中了勒索病毒 mercury。扩展名变为 mercury SQL Server数据库mdf文件中了…

mercurymw305r虚拟服务器,Mercury MW305R v3.0 路由器改造 LEDE(OpenWRT)

說明 1. 改造 Mercury MW305R v3.0(芯片 9533) 2. OpenWRT 版本:LEDE 17 3. 環境:Ubuntu 16.04 x64 第一步:修改硬件 1. 換 RAN 為 64M 2. 換 flash 為 16M 注:本教程主要說明制作鏡像部分,具體修改硬件步驟請參考:鏈接 第二步:獲取源碼 使用以下命令克隆我當時使用的版…

新的电脑如何连接网络连接无线网络连接服务器,新买的水星(MERCURY)路由器怎么设置才能连上宽带?...

问&#xff1a;新买的水星(MERCURY)路由器怎么设置才能连上宽带&#xff1f; 原来的路由器不好使了&#xff0c;新买了一个水星(MERCURY)路由器&#xff0c;自己设置到半天&#xff0c;还是不能上网。 新买的水星(MERCURY)路由器&#xff0c;要怎么设置才能连上宽带上网&#x…

水星路由器DNS服务器未响应,用手机设置水星(mercury)路由器WiFi的步骤

摘 要 用手机设置水星(mercury)路由器WiFi的步骤 xuyong 999文章 35评论 更多 我新买了一个水星的无线路由器,由于家里没有电脑,所以想用手机来设置。 可是我不知道手机设置水星路由 我新买了一个水星的无线路由器,由于家里没有电脑,所以想用手机来设置。 可是我不知道手机…