React 中hooks之useLayoutEffect 用法总结以及与useEffect的区别

React useLayoutEffect

1. useLayoutEffect 基本概念

useLayoutEffect 是 React 的一个 Hook,它的函数签名与 useEffect 完全相同,但它会在所有的 DOM 变更之后同步调用 effect。它可以用来读取 DOM 布局并同步触发重渲染。

2. useLayoutEffect vs useEffect

2.1 执行时机对比

Hook 名称执行时机执行方式使用场景
useEffectDOM 更新后且浏览器重新绘制屏幕之后异步执行 (组件渲染完成后)异步执行,不阻塞浏览器渲染大多数副作用,如数据获取、订阅
useLayoutEffectDOM 更新后且浏览器重新绘制屏幕之前同步执行(组件将要渲染时)同步执行,会阻塞浏览器渲染需要同步测量 DOM 或更新布局

2.2 执行顺序示例

function ExampleComponent() {const [count, setCount] = useState(0);useEffect(() => {console.log('useEffect 执行'); // 后执行});useLayoutEffect(() => {console.log('useLayoutEffect 执行'); // 先执行});return (<div onClick={() => setCount(c => c + 1)}>点击次数:{count}</div>);
}

3. useLayoutEffect 使用场景

3.1 DOM 测量和更新

function AutoHeight() {const [height, setHeight] = useState(0);const elementRef = useRef();useLayoutEffect(() => {// 在 DOM 更新后立即测量高度const element = elementRef.current;const elementHeight = element.getBoundingClientRect().height;if (elementHeight !== height) {// 立即更新高度,避免闪烁setHeight(elementHeight);}}, [height]);return (<div><div ref={elementRef} style={{ height: height || 'auto' }}>内容</div><div>当前高度: {height}px</div></div>);
}

3.2 防止闪烁的工具提示

function Tooltip({ text, position }) {const tooltipRef = useRef();const [tooltipPosition, setTooltipPosition] = useState(position);useLayoutEffect(() => {const tooltip = tooltipRef.current;const rect = tooltip.getBoundingClientRect();// 检查是否超出视口if (rect.right > window.innerWidth) {// 立即调整位置,避免闪烁setTooltipPosition({...position,left: position.left - (rect.right - window.innerWidth)});}}, [position]);return (<divref={tooltipRef}style={{position: 'absolute',...tooltipPosition}}>{text}</div>);
}

3.3 动画处理

function AnimatedComponent() {const elementRef = useRef();const [isVisible, setIsVisible] = useState(false);useLayoutEffect(() => {if (isVisible) {const element = elementRef.current;// 立即设置初始状态element.style.opacity = '0';element.style.transform = 'translateY(20px)';// 强制重排element.getBoundingClientRect();// 应用动画element.style.transition = 'opacity 0.5s, transform 0.5s';element.style.opacity = '1';element.style.transform = 'translateY(0)';}}, [isVisible]);return (<div><button onClick={() => setIsVisible(true)}>显示</button><div ref={elementRef}>动画内容</div></div>);
}

3.4 滚动位置同步

function ScrollSync({ content }) {const scrollContainerRef = useRef();useLayoutEffect(() => {const element = scrollContainerRef.current;// 内容更新后立即滚动到底部element.scrollTop = element.scrollHeight;}, [content]); // 当内容更新时执行return (<div ref={scrollContainerRef}style={{ height: '200px', overflow: 'auto' }}>{content.map((item, index) => (<div key={index}>{item}</div>))}</div>);
}

3.5 Modal 定位

function Modal({ isOpen, children }) {const modalRef = useRef();useLayoutEffect(() => {if (isOpen) {const modalElement = modalRef.current;const viewportHeight = window.innerHeight;const modalHeight = modalElement.getBoundingClientRect().height;// 立即计算并设置最佳位置modalElement.style.top = \`\${Math.max(0,(viewportHeight - modalHeight) / 2)}px\`;}}, [isOpen]);if (!isOpen) return null;return (<div className="modal-overlay"><div ref={modalRef} className="modal">{children}</div></div>);
}

4. 性能考虑

4.1 何时使用 useLayoutEffect

  • 需要同步测量 DOM 元素
  • 需要在视觉更新前进行 DOM 修改
  • 需要避免闪烁或布局抖动
  • 处理依赖于 DOM 布局的动画

4.2 何时使用 useEffect

  • 数据获取
  • 订阅事件
  • 日志记录
  • 其他不需要同步 DOM 测量或修改的副作用

5. 最佳实践

  1. 优先使用 useEffect
// ✅ 大多数情况下使用 useEffect 即可
useEffect(() => {// 异步操作,不影响渲染fetchData();
}, []);
  1. 仅在必要时使用 useLayoutEffect
// ✅ 需要同步 DOM 测量和更新时使用 useLayoutEffect
useLayoutEffect(() => {// 同步操作,立即更新 DOMupdateDOMPosition();
}, []);
  1. 注意性能影响
// ❌ 避免在 useLayoutEffect 中进行耗时操作
useLayoutEffect(() => {// 不要在这里进行大量计算或 API 调用heavyComputation();
}, []);// ✅ 耗时操作应该放在 useEffect 中
useEffect(() => {heavyComputation();
}, []);
  1. 合理使用依赖项
function OptimizedComponent({ data }) {useLayoutEffect(() => {// 只在真正需要同步更新的依赖项发生变化时执行}, [data.layout]); // 只依赖布局相关的属性
}

6. 注意事项

  1. useLayoutEffect 在服务器端渲染(SSR)中会收到警告,因为它只能在客户端执行
  2. 过度使用 useLayoutEffect 可能会导致性能问题
  3. 应该将耗时的操作放在 useEffect 中,只在 useLayoutEffect 中处理视觉相关的同步更新
  4. 在条件语句中使用时需要注意 Hook 规则

通过合理使用 useLayoutEffect 和 useEffect,我们可以更好地控制副作用的执行时机,优化用户体验,同时保持应用的性能。在实际开发中,应该根据具体场景选择合适的 Hook。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/2698.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 常用命令 - chmod 【改变文件或目录权限】

简介 “chmod” 这个命令来自于 “change mode” 的缩写&#xff0c;用于更改文件或目录的访问权限。这个命令允许用户设定谁可以读取、写入或执行一个文件。在 Linux 和其他类 Unix 系统中&#xff0c;文件权限对系统安全和用户隐私至关重要。 Linux/Unix 的文件调用权限分为…

Linux系统离线部署MySQL详细教程(带每步骤图文教程)

1、登录官网下载对应的安装包 MySQL :: Developer Zone 2、将压缩包上传到服务器上&#xff0c;这里直接上传到/usr/local路径上 使用sftp工具上传到/usr/local目录上 3、解压压缩包 tar -xf mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz 4、将mysql-8.0.39-linux-glibc2.17…

PyTorch使用教程(1)—PyTorch简介

PyTorch是一个开源的深度学习框架&#xff0c;由Facebook人工智能研究院&#xff08;FAIR&#xff09;于2016年开发并发布&#xff0c;其主要特点包括自动微分功能和动态计算图的支持&#xff0c;使得模型建立更加灵活‌。官网网址&#xff1a;https://pytorch.org。以下是关于…

Linux浅谈——管道、网络配置和客户端软件的使用

目录 一、管道 1、管道符 2、过滤功能 3、特殊功能 4、扩展处理 5、xargs命令扩展 二、网络配置 1、ifconfig查看网络信息 2、配置文件详解 网卡配置文件位置 3、systemctl查看网卡状态 4、systemctl启动/重启/停止网卡 三、客户端软件 1、什么是SSH 2、常用SSH终…

arcgis中生成格网矢量带高度

效果 1、数据准备 (1)矢量边界(miain.shp) (2)DEM(用于提取格网标高) (3)DSM(用于提取格网最高点) 2、根据矢量范围生成格网 模板范围选择矢量边界,像元宽度和高度根据坐标系来输入,我这边是4326的,所以输入的是弧度,输出格网矢量gewang.shp 3、分区统计 …

IEC103 转 ModbusTCP 网关

一、产品概述 IEC103 转 ModbusTCP 网关型号 SG-TCP-IEC103 &#xff0c;是三格电子推出的工业级网关&#xff08;以下简 称网关&#xff09;&#xff0c;主要用于 IEC103 数据采集、 DLT645-1997/2007 数据采集&#xff0c; IEC103 支持遥测和遥 信&#xff0c;可接…

Android BottomNavigationView不加icon使text垂直居中,完美解决。

这个问题网上千篇一律的设置iconsize为0&#xff0c;labale固定什么的&#xff0c;都没有效果。我的这个基本上所有人用都会有效果。 问题解决之前的效果&#xff1a;垂直方向&#xff0c;文本不居中&#xff0c;看着很难受 问题解决之后&#xff1a;舒服多了 其实很简单&…

【蓝桥杯】43687.赢球票

题目描述 某机构举办球票大奖赛。获奖选手有机会赢得若干张球票。 主持人拿出 N 张卡片&#xff08;上面写着 1⋯N 的数字&#xff09;&#xff0c;打乱顺序&#xff0c;排成一个圆圈。 你可以从任意一张卡片开始顺时针数数: 1,2,3 ⋯ ⋯ 如果数到的数字刚好和卡片上的数字…

(01)FreeRTOS移植到STM32

一、以STM32的裸机工程模板 任意模板即可 二、去官网上下载FreeRTOS V9.0.0 源码 在移植之前&#xff0c;我们首先要获取到 FreeRTOS 的官方的源码包。这里我们提供两个下载 链 接 &#xff0c; 一 个 是 官 网 &#xff1a; http://www.freertos.org/ &#xff0c; 另…

金融项目实战 05|Python实现接口自动化——登录接口

目录 一、代码实现自动化理论及流程 二、脚本实现的理论和准备工作 1、抽取功能转为自动化用例 2、搭建环境(测试工具) 3、搭建目录结构 三、登录接口脚本实现 1、代码编写 1️⃣api目录 2️⃣script目录 2、断言 3、参数化 1️⃣编写数据存储文件&#xff1a;jso…

C# .NetCore 使用 Flurl.Http 与 HttpClient 请求处理流式响应

AI对话接口采用流式返回&#xff1a; 1、使用Flurl处理返回的数据流 using Flurl; using Flurl.Http; [HttpPost] public async Task<string> GetLiushiChatLaw() { //1、请求参数&#xff0c;根据实际情况 YourModel request new YourModel();string allStr …

南京地铁路线和站点2021-2030含规划线路shp数据arcmap地铁图坐标wgs84无偏移内容分析测评

南京地铁路线与站点数据是地理信息系统&#xff08;GIS&#xff09;中常用的一种数据格式&#xff0c;主要用来表示城市轨道交通网络。在本压缩包中&#xff0c;包含的是2021年至2030年&#xff0c;包括规划线路的南京地铁信息&#xff0c;数据类型为Shapefile&#xff08;shp&…

Web3D交互展示:重塑产品展示的新维度

在当今数字化时代&#xff0c;如何高效、直观地展示产品成为企业营销的关键一环。传统的二维图片和视频展示虽然在一定程度上能够传达产品信息&#xff0c;但往往缺乏沉浸感和互动性&#xff0c;难以满足消费者日益增长的体验需求。在此背景下&#xff0c;Web3D交互展示应运而生…

JVM远程调试原理剖析

一、如何开启JVM远程调试 当一个 Java 应用启动时&#xff0c;JVM 会根据启动参数配置其运行环境。使用 -agentlib:jdwp 参数启动远程调试功能&#xff0c;JVM 会初始化调试代理。 agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 -jar your_application.jar…

人工智能之深度学习-[1]-了解深度学习

深度学习 深度学习&#xff08;Deep Learning&#xff09;是机器学习&#xff08;Machine Learning&#xff09;的一种方法&#xff0c;它通过模拟人脑的神经网络结构来进行学习和推理。深度学习使用多层神经网络来分析和建模数据&#xff0c;尤其擅长处理大量数据和复杂模式的…

【C语言】_字符串追加/连接函数strcat

目录 1. 函数声明与功能 2. 使用示例 3. 注意事项 4. 模拟实现 4.1 第一版&#xff1a;判空返回值对标strcatconst保证不可修改 4.2 第二版&#xff1a;优化\0的单独拼接 1. 函数声明与功能 char * strcat ( char * destination, const char * source ); strcat函数功能…

【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理

【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理 项目背景项目实现推理过程训练过程 项目展望写在最后项目下载链接 本文为原创文章&#xff0c;若需要转载&#xff0c;请注明出处。 原文地址&#xff1a;https://blog.csdn.net/qq_30270773/article…

【机器学习】制造业转型:机器学习如何推动工业 4.0 的深度发展

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 引言 在当今科技飞速发展的时代&#xff0c;制造业正经历着前所未有的变革&#xff0c;工业4.0的浪潮席卷而来。工业4.0旨在通过将…

半导体数据分析: 玩转WM-811K Wafermap 数据集(三) AI 机器学习

前面我们已经通过两篇文章&#xff0c;一起熟悉了WM-811K Wafermap 数据集&#xff0c;并对其中的一些数据进行了调用&#xff0c;生成了一些统计信息和图片。今天我们接着继续往前走。 半导体数据分析&#xff1a; 玩转WM-811K Wafermap 数据集&#xff08;二&#xff09; AI…

ClickHouse-CPU、内存参数设置

常见配置 1. CPU资源 1、clickhouse服务端的配置在config.xml文件中 config.xml文件是服务端的配置&#xff0c;在config.xml文件中指向users.xml文件&#xff0c;相关的配置信息实际是在users.xml文件中的。大部分的配置信息在users.xml文件中&#xff0c;如果在users.xml文…