为什么clearTimeout没有清除这个react组件中的超时?

问题描述 投票:0回答:4

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


  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();
  }

有趣的是,这有效:

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

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

javascript reactjs settimeout cleartimeout
4个回答
8
投票

问题是,在每次渲染时,

t
的值都会重置为空。一旦你调用
updateMessage
,它将触发重新渲染并丢失它的值。函数式 React 组件内的任何变量都会在每次渲染时重置(就像基于类的组件的
render
函数内一样)。如果您想保留引用,则需要使用
t
保存
setState
的值,以便可以调用
clearInterval

但是,解决这个问题的另一种方法是承诺

setTimeout
。通过做出承诺,您就不再需要
t
,因为在
setTimeout
完成之前它不会解决。完成后,您可以
updateMessage('')
重置
message
。这可以避免您在引用
t
时遇到的问题。

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

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

6
投票

我用 useEffect 解决了这个问题。 你想清除返回函数中的超时

const [message, updateMessage] = useState(msg);

useEffect(() => {
  const t = setTimeout(() => {
    console.log('wiping message');
    updateMessage('');
  }, 4000);

  return () => {
    clearTimeout(t)
  }
}, [message])



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

0
投票

您可以为此使用参考文献;

const timeoutRef = useRef<any>();

const clearLogger = () => {
  clearTimeout(timoutRef.current);

  timeoutRef.current = setTimeout(() => {
      console.log('wiping message');
      updateMessage('');
  }, 4000)
}

-1
投票

在clearTimeout()完成后尝试执行设置超时

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

        });

function clearTimeout(param, callback) {
  //`enter code here`do stuff
} 

或者你也可以使用 .then() 。

clearTimeout(param).then(function(){
     t = setTimeout(() => {
          console.log('wiping message');
          updateMessage('');
        }, 4000);
});
© www.soinside.com 2019 - 2024. All rights reserved.