当前位置: 首页 > news >正文

setTimeout定时器不生效- useRef 的特点/作用

问题:一个事件,触发后三秒执行,中间如果再次触发,重新计时,但是这个写法不生效,再次点击时,没有重新计时,怎么修改

原写法:

const viewAlert = (val) => {if (timeout) {clearTimeout(timeout)timeout = null}const { content, title, type } = valsetAlertInfo({ content, title, type })setShowAlert(true)timeout = setTimeout(() => {setShowAlert(false)}, 3000)}.

修改后:使用 useRef 来存储 timeout:这样可以避免每次渲染时都重新创建 timeout 变量

const viewAlert = (val) => {if (timeout.current) {clearTimeout(timeout.current);timeout.current = null;}const { content, title, type } = valsetAlertInfo({ content, title, type })setShowAlert(true)timeout.current = setTimeout(() => {setShowAlert(false)}, 3000)}// 清理定时器useEffect(() => {return () => {if (timeoutRef.current) {clearTimeout(timeoutRef.current);}};}, []);

使用普通变量 timeout 时没有生效,但在使用 useRef 存储 timeout 时成功了。

原因:

在这个例子中,每次 viewAlert 被调用时,timeout 都会被重新声明。假设你在第一次点击后设置了 timeout,然后在 1 秒后再次点击,第二次点击时 timeout 已经被重新声明为 null,因此 clearTimeout(timeout) 不会清除任何东西,新的 setTimeout 也不会覆盖旧的。

使用 useRef 存储 timeout 是正确的做法,因为它确保了定时器引用的持久性,避免了由于组件重新渲染导致的定时器问题

1️⃣ 函数组件的重新渲染:

在函数组件中,每次状态更新(例如 setAlertInfosetShowAlert)都会触发组件的重新渲染。

每次重新渲染时,函数内的所有局部变量(包括 timeout)都会被重新初始化。

2️⃣ timeout 变量的作用域:

当你使用普通变量 timeout 时,每次组件重新渲染时,timeout 都会被重新声明并初始化为 null.

因此,在 setTimeout 设置的回调函数执行之前,timeout 已经被重新初始化为 null,导致无法正确清除之前的定时器。

为什么 useRef 能解决问题

1️⃣ useRef 的持久性:

useRef 返回的对象在整个组件的生命周期内是持久存在的,不会随着组件的重新渲染而被重新初始化。

这意味着 timeoutRef.current 在多次点击之间保持引用,不会被重新声明为 null

2️⃣ 清除和设置定时器:

viewAlert 函数中,通过 timeoutRef.current 来清除和设置新的定时器。

即使组件重新渲染,timeoutRef.current 仍然指向同一个引用,因此可以正确地清除之前的定时器并设置新的定时器。

36.
http://www.dtcms.com/a/391614.html

相关文章:

  • 钻井的 “导航仪”:一文读懂单点、多点与随钻测量
  • CKS-CN 考试知识点分享(8) ingress 公开 https 服务
  • ​​[硬件电路-259]:LM4040AIM3 精密电压基准源: 管脚定义、概述、功能、技术指标、使用场景、原理
  • C语言:实现阶乘和计算
  • 鸿蒙应用开发——AppStorageV2和PersistenceV2的使用
  • shell脚本实现docker镜像批量保存并上传至Harbor仓库
  • 用 EzCaptcha 优化 reCAPTCHA 低通过率问题
  • 在docker中构建Vue项目
  • 力扣1895. 最大的幻方
  • Linux入门(四)
  • 以下是与LoRa技术相关的数学公式整理
  • (3) rust和前端交互
  • TextFlux重磅发布:告别复杂控制信号!多语种高保真场景文本编辑新时代
  • A股大盘数据-20250919分析
  • [x-cmd] X-CMD 的依赖非常精简,即装即用,无需额外配置
  • TM52F1363 电子元器件 海速芯 8位高性能微控制器(MCU)技术解析
  • 打工人日报#20250919
  • vue3学习日记(十九):组件实例详解
  • 【开题答辩全过程】以 基于python的订餐系统为例,包含答辩的问题和答案
  • 题解:CF2143E Make Good
  • 鸿蒙:使用worker实现多线程通信
  • Spring MVC 常用注解及代码示例
  • 【DMA】DMA入门:外设数据到内存,以串口DMA接收为例,解析底层实现
  • Java 中 super 和 this关键字总结
  • 我的创作纪念日 ----- 第512天
  • 【docker】删除镜像
  • 亚马逊 MWS 关键字 API 实战:关键字搜索商品列表接口深度解析与优化方案
  • 博文干货 | Pulsar 平均负载器(AvgShedder)
  • 【硬件】嘉立创专业版layout流程(一)
  • PyQt6之分组框