为什么 clearTimeout 不清除此反应组件中的超时? [英] Why is clearTimeout not clearing the timeout in this react component?

查看:68
本文介绍了为什么 clearTimeout 不清除此反应组件中的超时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在启动新的超时之前清除以前的超时,因为我希望消息显示 4 秒并消失,除非在 4 秒之前弹出新消息.问题:旧超时正在清除当前消息,因此 clearTimeout() 在此组件中不起作用,在这种情况下:

<预><代码>让 t;//t"代表计时器"const [message, updateMessage] = useState('此消息将出现 4 秒.除非有新消息替换它.');函数 clearLogger() {清除超时(t);t = setTimeout(() => {console.log('擦除消息');更新消息('');}, 4000);}函数 initMessage(msg) {更新消息(味精);清除记录器();}

有趣的是,这是有效的:

 函数 clearLogger() {t = setTimeout(() => {console.log('擦除消息');更新消息('');}, 4000);清除超时(t);}

...但显然违背了目的,因为它会立即消除超时.在实践中,我应该能够每两秒触发一次 initMessage() 并且永远不会看到擦除消息"记录到控制台.

解决方案

问题是在每次渲染时 t 的值都被重置为 null.一旦你调用 updateMessage,它就会触发重新渲染并失去它的价值.功能性反应组件中的任何变量在每次渲染时都会重置(就像在基于类的组件的 render 函数中一样).如果要保留引用,则需要使用 setState 保存 t 的值,以便调用 clearInterval.

然而,另一种解决方法是promisify setTimeout.通过使其成为承诺,您可以删除对 t 的需求,因为它在 setTimeout 完成之前不会解析.完成后,您可以updateMessage('') 重置message.这可以避免您在引用 t 时遇到的问题.

clearLogger = () =>{return new Promise(resolve => setTimeout(() => updateMessage(''), resolve), 5000));};const initMessage = async (msg) =>{更新消息(味精);等待 clearLogger();}

I am attempting to clear a former timeout before initiating a new timeout, because I want messages to display for 4 seconds and disappear UNLESS a new message pops up before the 4 seconds is up. The Problem: Old timeouts are clearing the current message, so clearTimeout() is not working in this component, in this scenario:


  let t; // "t" for "timer"

  const [message, updateMessage] = useState('This message is to appear for 4 seconds. Unless a new message replaces it.');

  function clearLogger() {
    clearTimeout(t);
    t = setTimeout(() => {
      console.log('wiping message');
      updateMessage('');
    }, 4000);
  }

  function initMessage(msg) {
    updateMessage(msg);
    clearLogger();
  }

The funny thing is that this works:

  function clearLogger() {
    t = setTimeout(() => {
      console.log('wiping message');
      updateMessage('');
    }, 4000);
    clearTimeout(t);
  }

...but obviously defeats the purpose, since it just immediately obliterates the timeout. In practice, I should be able to trigger initMessage() every two seconds and never see, "wiping message' logged to the console.

解决方案

The issue is that on every render the value of t is reset to null. Once you call updateMessage, it will trigger a re-render and will lose it's value. Any variables inside a functional react component get reset on every render (just like inside the render function of a class-based component). You need to save away the value of t using setState if you want to preserve the reference so you can call clearInterval.

However, another way to solve it is to promisify setTimeout. By making it a promise, you remove needing t because it won't resolve until setTimeout finishes. Once it's finished, you can updateMessage('') to reset message. This allows avoids the issue that you're having with your reference to t.

clearLogger = () => {
  return new Promise(resolve => setTimeout(() => updateMessage(''), resolve), 5000));
};

const initMessage = async (msg) => {
  updateMessage(msg);
  await clearLogger();
}

这篇关于为什么 clearTimeout 不清除此反应组件中的超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆