React Hooks,useEffect 中的 setTimeout 直到结束才触发,因为状态更新

2024-03-24

Context:

  • 添加新消息(例如,每两秒,使用 setInterval)。
  • 消息有状态,可以是旧的,也可以是新的。新添加的消息有一个“新”标志。
  • 每 5 秒后,所有“新”消息都会被指定为“旧”消息。 (设置超时)

Problem:

  • 直到结束才触发超时。添加新消息,但在添加所有消息之前它们仍保持“新”状态。
  • 我怀疑每次更新后超时都会被重置/清除,并且因为更新发生的速度比超时快,所以超时回调永远不会及时触发(因此只有最终的超时被触发)。

function useInterval(callback, delay) {
  const savedCallback = React.useRef();
  // Remember the latest callback.
  React.useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);
  // Set up the interval.
  React.useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

const defaultMessages = [
  {
    message: "message 1",
    new: false
  },
  {
    message: "message 2",
    new: false
  },
  {
    message: "message 3",
    new: true
  }
];

export default function App() {
  const [messages, setMessages] = React.useState(defaultMessages);
  const messagesRef = React.useRef(messages);

  messagesRef.current = messages;

  // add a new message every 2 seconds
  useInterval(() => {
    messages.length < 10 &&
      setMessages([
        ...messages,
        { message: `message ${messages.length + 1}`, new: true }
      ]);
  }, 2000);

  React.useEffect(() => {
    const timer = setTimeout(() => {
      // console.log("change all messages from new to old");
      const updateMessages = messagesRef.current.map(m => ({
        ...m,
        new: false
      }));
      setMessages([...updateMessages]);
    }, 5000); // if you change this to duration less than 2 seconds then it runs just fine
    return () => clearTimeout(timer); // removing the timer, calls it with every message update and seemingly ignores the timeout duration
  });

  return (
    <div className="App">
      {messages.map(m => (
        <div key={m.message}>
          {m.message}, status: {m.new ? "new" : "old"}
        </div>
      ))}
    </div>
  );
}

示例代码: https://codesandbox.io/s/settimeout-resetting-with-updates-ufl3b https://codesandbox.io/s/settimeout-resetting-with-updates-ufl3b

不知道如何使用 React Hooks api 来解决这个问题。每次更新后超时需要持续五秒。现在,每次暂停似乎都被取消或被后面的暂停排队。我很困惑。

谢谢你!


嗯,我注意到的主要问题是清除超时下一个渲染,这意味着,如果渲染速度足够快,您实际上会取消超时回调而不是运行它。

 React.useEffect(() => {
    const timer = setTimeout(() => {});
    // will clear the timeout on ***next*** render!
    return () => clearTimeout(timer);
  });

因此,在修复它并使用功能更新而不是引用之后,这段代码似乎有效:

export default function App() {
  const [messages, setMessages] = React.useState(defaultMessages);

  // add a new message every 2 seconds
  useInterval(() => {
    messages.length < 10 &&
      setMessages(prev => [
        ...prev,
        { message: `message ${messages.length + 1}`, new: true }
      ]);
  }, 2000);

  React.useEffect(() => {
    console.log("rendered");
    setTimeout(() => {
      setMessages(prev =>
        prev.map(m => ({
          ...m,
          new: false
        }))
      );
    }, 3000);
  });

  return (
    <div className="App">
      {messages.map(m => (
        <div key={m.message}>
          {m.message}, status: {m.new ? "new" : "old"}
        </div>
      ))}
    </div>
  );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Hooks,useEffect 中的 setTimeout 直到结束才触发,因为状态更新 的相关文章

  • 如何判断一个网页是否支持jquery?

    确定网页是否启用 jquery 的最佳方法是什么 如果这是确定它的最佳方法 则使用 jquery 本身 if jQuery jquery object exists jQuery 并不神奇 它本质上只是一个大对象 您可以像检查任何其他对象一
  • Eslint 从另一个文件确定全局变量

    我试图以这样的方式设置 ESLint 使其在对实际目标文件进行 linting 之前解析全局声明文件 这样我就不必将所有确实是全局的函数和变量声明为全局 而是让解析器弄清楚 In 一些 模块 js function do something
  • 如何在 DOM 中的每个元素中调用函数,即使它们是动态创建的

    我想对 DOM 上的特定元素调用函数 例如 red css backgroundColor pink 它适用于 DOM 中已经存在的任何元素 但我也希望在动态添加到 DOM 的元素中调用此方法 我尝试过类似的事情 red on functi
  • 我点击的号码没有出现在反应项目的屏幕上

    当我尝试在屏幕中呈现点击的数字时 该数字没有出现 但它确实可以在控制台中显示 我不知道如何修复它应该在屏幕上 号码 旁边应用的号码 import render from testing library react import React
  • 使用 jQuery Select2 清除下拉菜单

    我正在尝试使用奇妙的方式以编程方式清除下拉菜单Select2 http ivaynberg github com select2 图书馆 使用 Select2 远程 ajax 调用动态填充下拉列表query option HTML
  • 在随机位置启动 HTML5

    我有一个大约 2 小时长的音轨 我想在我的网站上使用它 我希望它在页面加载时在随机位置开始播放曲目 使用 HTML5 可以吗 我知道您可以使用 element currentTime 函数来获取当前位置 但是如何在完全下载之前获取曲目的总时
  • Mapbox GL 中的 MaxBounds 和自定义非对称填充

    我有一个 Mapbox GL JS 应用程序 在地图上显示一些小部件 为了确保地图上的任何内容都不会被它们隐藏 我使用以下命令添加了一些填充map setPadding 这是一个不对称的 在我的例子中左边比右边大 它按预期工作 例如fitB
  • 检测 Google 验证码的挑战窗口何时关闭

    我正在使用谷歌隐形验证码 有没有办法检测挑战窗口何时关闭 我所说的挑战窗口是指您必须选择一些图像进行验证的窗口 目前 我在按钮上放置了一个旋转器 一旦单击按钮 就会呈现验证码挑战 无法向用户提示另一个质询窗口 我以编程方式调用渲染函数 gr
  • API 使用令牌向 odoo 进行身份验证

    我想使用令牌从 Express 应用程序向 Odoo 进行身份验证 我在用odoo xmlrpc https www npmjs com package odoo xmlrpc连接 Odoo 的节点模块 我的快递应用程序 Odoo 要求 A
  • React JS 服务器端问题 - 找不到窗口

    你好 我正在尝试在我的reactJS项目中使用react rte 我有服务器端渲染 每次我想使用这个包时 我都会得到 return msie 6 9 b test window navigator userAgent toLowerCase
  • 为什么这行带有“await”的代码会触发微任务队列处理?

    以下引用是我理解微任务队列处理的主要参考 当 JS 堆栈清空时 就会处理微任务 承诺使用 杰克 阿奇博尔德 https twitter com jaffathecake status 954653170986311680 这对我来说没有意义
  • 将 Firebase FCM 添加到 ReactJS 应用程序

    我正在尝试向我的 ReactJS 应用程序中的用户发送推送通知 我已添加 firebase 请求用户通知权限 这正在发挥作用 但现在我想注册设备令牌 但这给了我错误 消息传递 我们无法注册默认的 Service Worker 无法注册 Se
  • 全局传递 xhr onload 函数的值

    在我正在创建的应用程序中 我有以下 XMLHttpRequest 并且我正在尝试传递结果data在 的里面xhr onload 到在同一父函数中创建的数组中 var url http api soundcloud com resolve j
  • 如果没有 /// 标签,TypeScript 的“将 JavaScript 输出合并到文件中”选项无法推断出正确的脚本顺序

    我正在开发一个使用 将 JavaScript 输出合并到文件中 选项的 TypeScript 解决方案 我经常引用另一个文件中定义的项目 例如 In MyBaseClass ts export class MyBaseClass In My
  • 如何动态调整jqgrid到当前窗口大小?

    如何动态调整jqgrid到当前窗口大小 基于javascript jQuery 最好的例子在这里 TinyMCE 去 http www tinymce com tryit full php http www tinymce com tryi
  • 扩展 RegExp 以获取文件扩展名

    我知道 已经有很多基于 RegExp 的解决方案 但是我找不到适合我需求的解决方案 我有以下函数来获取 URL 的各个部分 但我还需要文件扩展名 var getPathParts function url var m url match w
  • ChartJs:如何按时间值(而不是像素)以编程方式平移

    我使用的是chartJs 3 6 1 和 Chartjs plugin zoom 1 2 1 但我认为这并不重要 我有 2 个时间序列折线图 当我通过拖放平移一个图表时 我也想移动 平移另一个图表 为此 我为 graphA 启用了缩放 平移
  • ThreeJS 中阴影的奇怪行为

    所以我有一个 ThreeJS 场景 并且添加了一些球体 多材质 我还添加了定向光 this light new THREE DirectionalLight 0xFFFFFF 1 this light position set 2 10 2
  • 以角度访问窗口 TemplateUrl 内的范围

    我的模式有一个 windowTemplateUrl 如下 div class modal fade div class modal dialog div class modal content square btn div div div
  • d3.event.translate 在触摸设备的缩放上包含 NaN

    我使用 d3 为我的 svg 编写了一个自定义缩放函数 如下所示 Zoom behavior function myzoom xpos d3 event translate 0 ypos d3 event translate 1 vis a

随机推荐

  • Pow() 计算错误?

    我需要在我的 C 程序中使用 pow 如果我调用pow 这样运行 long long test pow 7 e Where e 是一个整数值 值为 23 我总是得到821077879因此 如果我用Windows计算器计算它我得到273687
  • 奇怪的@IBAction 冲突或错误? (迅速)

    所以我得到了我的简单 iOS 应用程序的代码 当我按下 touchPressed 按钮时 该按钮应该在屏幕上获得一个新的随机位置 并且 labelScore 应该根据按钮触摸的次数进行自我更新 我的一个朋友在 Objective C 中尝试
  • 如何使用 HTTPClient 设置 HTTP 请求标头“身份验证”?

    我想在向服务器发送 POST 请求时设置 HTTP 请求标头 授权 我该如何在 Java 中做到这一点 HttpClient 有支持吗 http www w3 org Protocols HTTP HTRQ Headers html z9
  • ExpandableTextView 中的复制功能在更改方向时会产生错误

    我在片段中创建了一些可扩展的文本视图 但没有启用复制功能 即使我改变方向 这也能正常工作 但当我给android textIsSelectable true 在 xml TextView 中 我面临的问题是 当改变方向时 所有 TextVi
  • 如何将 Spark Dataframe 推送到 Elastic Search (Pyspark)

    初学者 ES 问题在这里 将 Spark Dataframe 推送到 Elastic Search 的工作流程或步骤是什么 根据研究 我相信我需要使用Spark newAPIHadoopFile https spark apache org
  • 建模/记录功能程序

    我发现 UML 对于记录 OO 系统的各个方面非常有用 特别是用于总体架构的类图和用于说明特定例程的序列图 我想为我的 clojure 应用程序做同样的事情 我目前对模型驱动开发不感兴趣 只是对交流应用程序如何工作感兴趣 UML 是函数式编
  • 向 HashMap 添加一个键而不添加值?

    有没有一种方法可以在不添加值的情况下向 HashMap 添加键 我知道这看起来很奇怪 但我有一个HashMap
  • 一个意料之外的问题发生了。请稍后再试。 (3200000)

    任何人都可以在 Google Play 商店中的管理发布中遇到问题吗 当我尝试在生产轨道上上传应用程序时 没开啊我收到这个错误 An unexpected error occurred Please try again later 3200
  • Laravel - 嵌套关系中的 orderBy

    我有一个这样雄辩的查询 Forum with comments user gt find id 这将返回一个嵌套结果forum gt its comments gt user who commented 我该如何申请orderBy on c
  • API java 5 及更多:我应该返回数组还是集合?

    本着最佳实践 始终返回 从不返回 https stackoverflow com questions 171156 best practices always return a never a 我在即将到来的文章中面临类似的问题从 JDK1
  • 没有突变的 AWS AppSync 订阅

    阅读 AppSync 文档 似乎 AppSync 订阅只能通过将订阅附加到突变来工作 但是 如果我需要独立于突变的订阅怎么办 这是由于某些内部状态变化而引发的吗 例如 如果有新资源可用 AppSync 中可以这样做吗 如果没有突变 这是不可
  • MvxImageView,无法将ImageUrl绑定到本地资源

    我将 MvvmCross 3 0 14 与 Xamarin Android 一起使用 我有一个 MvxImageView 如果我使用 android src 直接指定图像 不绑定 我可以显示特定的本地图形资源
  • 如何在 matplotlib 中通过彩虹设置箱线图颜色

    我想创建数据箱线图进行比较 我的图看起来像 我怎样才能添加颜色 您可以为以下框着色这个例子 https matplotlib org examples statistics boxplot color demo html 除此之外 您还需要
  • MySQL 表行中的时间和日期戳

    我想在添加到 MySQL 表的每一行上添加时间和日期戳 如果我理解正确 我需要为时间和日期戳创建一列 如何为下面的 CREATE TABLE 查询执行此操作 CREATE TABLE table id INT 11 NOT NULL aut
  • Arduino 的 C++ 类文件中的字符串无法编译

    我正在用 C 为 Arduino 编写一个堆栈类sketch http www arduino cc en Tutorial Sketch 我相信它完全符合AVR 如果这就是它的名字 我记不清了 编译器 我都用过malloc and fre
  • 无法解决:com.google.android.gms:在 IntelliJ Idea 中使用 gradle 播放服务

    我正在尝试将 google play 服务添加到 IntelliJ Idea 中的 libGDX 项目中 我已按照此处的设置指南进行操作 https developers google com android guides setup ht
  • PHP/MySQL 命名约定:camelCase 与 under_score?

    在 PHP 模型代码中 至少在我自己的此类代码中 经常会直接引用 MySQL 表和字段名称 并且由于 MySQL 标识符大部分不区分大小写 因此我通常使用下划线命名约定来使这些标识符成为更具可读性 但与此同时 似乎大多数人在创建 PHP 类
  • 记录 ASP.NET 4.0 中的带宽使用情况和请求时间

    我正在编写一个 ASP NET 应用程序 它将跟踪正在使用的带宽以及每个请求所花费的时间 由于我的应用程序将托管在共享服务器上 因此我希望在 ASP NET 本身而不是 IIS 级别上完成所有操作 虽然有一些称为性能计数器的东西 但它们会说
  • 在 QuickFix 中,RelatedSymGroup 顺序设置的是什么

    相关这个问题 https stackoverflow com questions 32012881 quickfixj swaps group order交易对手提供商引擎以某种方式设置为检查 FIX 标签的组顺序并拒绝任何不符合预期顺序的
  • React Hooks,useEffect 中的 setTimeout 直到结束才触发,因为状态更新

    Context 添加新消息 例如 每两秒 使用 setInterval 消息有状态 可以是旧的 也可以是新的 新添加的消息有一个 新 标志 每 5 秒后 所有 新 消息都会被指定为 旧 消息 设置超时 Problem 直到结束才触发超时 添