In my React component, I have a event handling for beforeunload. I want to clean that up in my useEffect return. Is the below code the correct way of doing the same or is there any better way ?
useEffect(() => {
if (Object.keys(someKey).length > 0) {
function callSvc(urls) {
}
callSvc(urls);
const intV = setInterval(callSvc, interval, urls);
window.addEventListener("beforeunload", function() {clearInterval(intV)});
return () => {
//window.removeEventListener("beforeunload", function() {clearInterval(intV)});
}
}
}, [someKey])
UPDATED CODE
useEffect(() => {
if (Object.keys(someKey).length > 0) {
const intV = setInterval(callSvc, interval, urls);
function clearTimer() {
clearInterval(intV)
}
window.addEventListener("beforeunload", clearTimer);
return () => {
window.removeEventListener("beforeunload", clearTimer);
}
}
}, [someKey])
Is the below code the correct way of doing the same or is there any better way ?
There is a crucial problem with your code: Removing an event handler only works if you pass exactly the same function to removeEventListener that you passed to addEventListener. But as it stands you are passing two different functions. This is easy to solve buy storing the function in a variable and reference that variable in both addEventListener and removeEventListener.
However, I question whether the beforeunload event handler is even necessary. When the page is closed any JS code stops running anyway. I think it's more important to stop the interval when the effect re-runs, otherwise you are starting a new interval whenever the effect runs again, resulting in multiple parallel intervals:
useEffect(() => {
if (Object.keys(someKey).length > 0) {
function callSvc(urls) {
}
callSvc(urls);
const intV = setInterval(callSvc, interval, urls);
return () => {
clearInterval(intV)
}
}
}, [someKey])
This is the correct way to return a function inside if-block, useEffect() will clean-up only if condition in if-statement is true, but when is no listener to add, there is no needed to clean-up on top level inside the useEffect() function.
useEffect(()=>{
let getThere = someBoolean
if (getThere) {
console.log("Listener Added.")
return () => {
console.log("Listener Removed. (Inside If statement)")
}
}
return () => {
console.log("No Listener to Remove.")
}
},[])
Then test switching the page by mount/unmount (I'm currently using react-router-dom) then watch the console.
if condition is true
Listener Added.
Listener Removed. (Inside If statement)
If condition is false
No Listener to Remove.
If the boolean is true the function will return the fucntion inside the if-block only, not flow into the outer return, except that the boolean is false, the code will go to return at outer level.