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 直到结束才触发,因为状态更新 的相关文章

  • Pug 从模板内的另一个文件调用 js 函数

    我花了将近四个小时都无法解决这个问题 而且我找不到任何针对此类问题的有用文档 这就是问题 我正在使用 pug jade 模板 我想调用 pug 模板内的函数来转换一些数据 这是主要模板 main template section each
  • 为什么 Promise `.then` 方法的回调是反模式

    我在 StackOverflow 上看到了答案 人们建议为 AngularJS 服务提供回调函数 app controller tokenCtrl function scope tokenService tokenService getTo
  • querySelector 搜索直接子级[重复]

    这个问题在这里已经有答案了 我有一些类似 jquery 的函数 function elem return gt someselector elem 问题是我怎样才能做同样的事情querySelector 问题是 gt 选择器中querySe
  • 鼠标移动时画布拖动

    我正在尝试构建一个可以使用鼠标移动拖动的画布 我做了一些我无法理解的错误 因为一开始似乎有效 然后出现了一个增量错误 使画布移动得太快 考虑以下代码 window onload function var canvas document ge
  • 如何在 Windows 网络中的 Intranet Web 应用程序中获取用户的用户名

    我内部有一个简单的 HTML 页面 它只显示一个表单并要求用户填写 我想自动捕获Windows域用户名和机器名 并将其与表单中收集的数据一起提交 我可以在客户端这样做吗 HTML JavaScript 或者我被迫在服务器端执行此操作 我还不
  • ASP.NET 验证控件和 Javascript 确认框

    我有一个使用 NET 服务器端输入验证控件的页面 此页面还有一个 javascript 确认框 在提交表单时会触发该确认框 当前 当选择 提交 按钮时 会出现 javascript 确认框 一旦确认 就会触发 ASP NET 服务器端验证控
  • 替换img路径jquery

    我正在尝试替换 jquery 中的 img 路径 注入远程页面 replaceexample com thumbs withexample com images 我已经尝试过这个 但似乎不起作用 img attr src replace t
  • 为某个时刻添加持续时间 (moment.js)

    时刻版本 2 0 0 阅读文档后 http momentjs com docs manipulating add 我认为这很简单 Chrome 控制台 var timestring1 2013 05 09T00 00 00Z var tim
  • 如何将焦点设置在 BootStrap 中的第一个输入字段上? [复制]

    这个问题在这里已经有答案了 可能的重复 如何将焦点设置到独立于 id 的 HTML 表单中的第一个输入元素 https stackoverflow com questions 277544 how to set the focus to t
  • 为什么这个递归函数返回未定义?

    我正在尝试编写一个使用递归组合两个字符串的函数 我的代码如下 但我不知道为什么该函数返回未定义 特别是当我在基本情况下使用 console log 时 它不会打印未定义而是打印正确的值 var str3 function merge str
  • 如何将React JS状态保存到本地存储中

    我不知道如何将 React js 状态存储到本地存储中 import React Component from react import App css import auth createUserProfileDocument from
  • 使用 eval 时不会受到 XSS 威胁

    我正在制作 不是现在 但我仍然对这个感到好奇 一款使用 HTML5 和 JS 的游戏 我想要的是人们可以插入自定义脚本 但要安全 function executeCustomJS code eval code bad 当然这段代码非常糟糕
  • 为什么浏览器允许onmousedown JS改变href?

    我很长时间以来都注意到 当您尝试复制链接位置或在 Facebook 上打开链接时 它会修改链接并将其传递给l php 例如 我可以被发送到 http www facebook com l php u http 3A 2F 2Fwww goo
  • iPhone 上的锁定方向 UIWebView

    有没有办法锁定 UIWebView 的方向 使用 Obj C JS 还是 Html 我不想有按钮或任何东西 我只想在应用程序打开时将其锁定为纵向 好像这个堆栈溢出帖子 https stackoverflow com questions 43
  • 如何在MUI GridList中实现图块的水平滚动?

    这是我的 JS 页面 我需要在其中实现GridList组件显示多个图块 并且在列表大小超出屏幕限制后可水平滚动 import React useState from react import Header from common heade
  • 为什么 console.log() polyfill 不使用 Function.apply()?

    我一直在看一些流行的console log 包装 填充 保罗 爱尔兰的 http paulirish com 2009 log a lightweight wrapper for consolelog 本阿尔曼的 http benalman
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • Firebase 身份验证和实时应用程序数据库如何保护自身安全?

    从一般开发的角度来看 我很好奇如何保护在线资源的访问 我们使用以下 Firebase 配置参数初始化 Web 应用程序 apikey authdomain projectid databaseurl messagesenderid 服务器如
  • HTML5 地理定位 - 在 iOS 上无法始终工作

    目前正在使用 HTML5 地理定位 我已经在所有网络浏览器上测试了它 它似乎工作正常 然而 当我在 iPad 上测试地理定位时 它在 iPad mini 上始终有效 但当我将其放在更大的 iPad iPad 2 上时 位置似乎并不总是有效
  • 在引导程序中以编程方式更改选项卡窗格选项卡

    我使用的选项卡窗格定义为 ul class nav nav tabs li a href personal Personal Information a li li class active a href contact Contact 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 直到结束才触发超时 添