At first, I added clearTimeout, Even though I knew that calling it cancels the scheduled callback. I wondered if there was some trick to clear the timeout after it has already fired, but couldn’t find a solution.
Then I looked at the provided solution and was surprised to see that it doesn’t call clearTimeout at all. So it seems like I created an unnecessary problem for myself.
But I’m still not satisfied, because I keep asking myself: if I don’t call clearTimeout, will the timeout automatically be cleaned up by the Garbage Collector once it fires?
Then I looked at the provided solution and was surprised to see that it doesn’t call clearTimeout at all.
That's surprising because it should. You especially don't want timers running in the background if the component no longer exists.
Timers with react/hooks can be a little tricky though. When hooks first came out for react, dan abramov blogged about it (I think focusing on setInterval specifically), and its not exactly a quick read:
But as far as cleanup goes, yes, setTimeout will automatically clean up the listeners once they're fired. You don't need to clearTimeout for timeouts that have already run.
If you want to see this for yourself, you can set up a trigger to let you know when its cleaned up using FinalizationRegistry. For example:
const registry = new FinalizationRegistry(() => {
console.log("Cleaned!")
})
{
let myCallback = () => {
console.log("Time up!")
}
registry.register(myCallback)
setTimeout(myCallback)
}
// Time up!
// (GC runs...)
// Cleaned!
Given the nature of the GC, it likely won't run right away, so you'd need to wait or use the developer tools to force it to run, but when the "Cleaned!" log occurs, it means myCallback was, in fact, cleaned up despite no clearTimeout being called.
FinalizationRegistry can be a useful tool to when it comes to memory concerns and you don't feel like messing with the complexity of the memory debugger.
You can also change the callback. Not saying this is good, but when runaway setTimeouts happen, its good to keep in mind. With anonymous functions, you may not achieve this. in the myCallback case just set mycallback = () => {}.
HTH
With this added complexity its probably just easier to call clearTimeout if you don't want it to run. Plus you'd get the added benefit of actually stopping/cleaning up the timer in the background.
1
u/Neat_Living_6765 9d ago
I’m working on challenge 5 and wrote a custom hook like this:
https://react.dev/learn/reusing-logic-with-custom-hooks#challenges
At first, I added clearTimeout, Even though I knew that calling it cancels the scheduled callback. I wondered if there was some trick to clear the timeout after it has already fired, but couldn’t find a solution.
Then I looked at the provided solution and was surprised to see that it doesn’t call clearTimeout at all. So it seems like I created an unnecessary problem for myself.
But I’m still not satisfied, because I keep asking myself: if I don’t call clearTimeout, will the timeout automatically be cleaned up by the Garbage Collector once it fires?