Reputation: 1052
I need to update date after 12 am. So, I am setting a recursive timer to calculate seconds till next day and update If user is on the same screen. I am noticing that the timer unsubscribe function never gets called (whether the app goes in background, app is killed or navigation state changes)
const [selectedDate, setSelectedDate] = useState(new Date());
let timer;
useEffect(() => {
console.log("RENDERING");
updateDateAfter12am();
return () => {
console.log("CLEARING TIMER");
clearTimeout(timer);
};
}, []);
const updateDateAfter12am = () => {
const currentDate = new Date();
const secondsUntilEndOfDate = getSecondsUntilEndOfDate(currentDate);
timer = setTimeout(() => {
if (isSameDay(selectedDate, currentDate)) {
setSelectedDate(new Date());
}
updateDateAfter12am();
}, secondsUntilEndOfDate * 1000);
};
const isSameDay = (d1, d2) => {
return (
d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate()
);
};
const getSecondsUntilEndOfDate = (d) => {
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
return 24 * 60 * 60 - h * 60 * 60 - m * 60 - s;
};
Upvotes: 0
Views: 869
Reputation: 6607
I have created a very simple code sandbox to test your code, and it looks like it is behaving correctly: the useEffect
cleanup function is being called whenever the component is unmounted, as stated in the docs.
import React from "react";
import "./styles.css";
export default function App() {
const [mounted, setMounted] = React.useState(true);
return (
<div className="App">
<button onClick={() => setMounted((prev) => !prev)}>Mount/Unmount</button>
{mounted && <Test />}
</div>
);
}
const Test = () => {
const [selectedDate, setSelectedDate] = React.useState(new Date());
let timer;
React.useEffect(() => {
console.log("RENDERING");
updateDateAfter12am();
return () => {
console.log("CLEARING TIMER");
clearTimeout(timer);
};
}, []);
const updateDateAfter12am = () => {
const currentDate = new Date();
const secondsUntilEndOfDate = getSecondsUntilEndOfDate(currentDate);
timer = setTimeout(() => {
if (isSameDay(selectedDate, currentDate)) {
setSelectedDate(new Date());
}
updateDateAfter12am();
}, secondsUntilEndOfDate * 1000);
};
const isSameDay = (d1, d2) => {
return (
d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate()
);
};
const getSecondsUntilEndOfDate = (d) => {
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
return 24 * 60 * 60 - h * 60 * 60 - m * 60 - s;
};
return <p>{selectedDate.toString()}</p>;
};
So the problem might be that you are not actually unmounting your component. If you need help with that, you should post a Complete, Minimal, Reproducible example.
Upvotes: 1