为什么 clearTimeout 不清除此反应组件中的超时?
Why is clearTimeout not clearing the timeout in this react component?
我试图在启动新的超时之前清除以前的超时,因为我希望消息显示 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() 并且永远不会看到“擦除消息”记录到控制台。
问题是在每次渲染时 t
的值都重置为 null。一旦你调用 updateMessage
,它将触发重新渲染并失去它的价值。功能性 React 组件内的任何变量都会在每次渲染时重置(就像在基于 class 的组件的 render
函数内一样)。如果要保留引用,则需要使用 setState
保存 t
的值,以便可以调用 clearInterval
.
然而,另一种解决方法是 promisify setTimeout
。通过承诺,您可以删除 t
的需求,因为在 setTimeout
完成之前它不会解决。完成后,您可以 updateMessage('')
重置 message
。这可以避免您在引用 t
.
时遇到的问题
clearLogger = () => {
return new Promise(resolve => setTimeout(() => updateMessage(''), resolve), 5000));
};
const initMessage = async (msg) => {
updateMessage(msg);
await clearLogger();
}
尝试在 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);
});
我用 useEffect 解决了这个问题。你想在return函数
中清除超时
const [message, updateMessage] = useState(msg);
useEffect(() => {
const t = setTimeout(() => {
console.log('wiping message');
updateMessage('');
}, 4000);
return () => {
clearTimeout(t)
}
}, [message])
function initMessage(msg) {
updateMessage(msg);
}
我试图在启动新的超时之前清除以前的超时,因为我希望消息显示 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() 并且永远不会看到“擦除消息”记录到控制台。
问题是在每次渲染时 t
的值都重置为 null。一旦你调用 updateMessage
,它将触发重新渲染并失去它的价值。功能性 React 组件内的任何变量都会在每次渲染时重置(就像在基于 class 的组件的 render
函数内一样)。如果要保留引用,则需要使用 setState
保存 t
的值,以便可以调用 clearInterval
.
然而,另一种解决方法是 promisify setTimeout
。通过承诺,您可以删除 t
的需求,因为在 setTimeout
完成之前它不会解决。完成后,您可以 updateMessage('')
重置 message
。这可以避免您在引用 t
.
clearLogger = () => {
return new Promise(resolve => setTimeout(() => updateMessage(''), resolve), 5000));
};
const initMessage = async (msg) => {
updateMessage(msg);
await clearLogger();
}
尝试在 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);
});
我用 useEffect 解决了这个问题。你想在return函数
中清除超时const [message, updateMessage] = useState(msg);
useEffect(() => {
const t = setTimeout(() => {
console.log('wiping message');
updateMessage('');
}, 4000);
return () => {
clearTimeout(t)
}
}, [message])
function initMessage(msg) {
updateMessage(msg);
}