fix(web): clear announcement stagger timers on unmount

The cleanup for the announcement-toast effect only cleared the outer
1500ms timer, leaving the per-announcement stagger timers (i * 800ms)
untracked. If the root layout unmounts during the stagger window, those
timers fire after cleanup and attempt to toast against a dead tree.

Track the inner timer ids in an array and clear them alongside the outer
timer in the effect cleanup.

Fixes #1094.
This commit is contained in:
Tim Ren 2026-04-15 20:07:20 +08:00
parent 656e061f84
commit c03a1e177a

View file

@ -65,7 +65,9 @@ export function AnnouncementToastProvider() {
if (hasChecked.current) return;
hasChecked.current = true;
const timer = setTimeout(() => {
const staggerTimers: ReturnType<typeof setTimeout>[] = [];
const outerTimer = setTimeout(() => {
const authed = isAuthenticated();
const active = getActiveAnnouncements(announcements, authed);
const importantUntoasted = active.filter(
@ -74,11 +76,16 @@ export function AnnouncementToastProvider() {
for (let i = 0; i < importantUntoasted.length; i++) {
const announcement = importantUntoasted[i];
setTimeout(() => showAnnouncementToast(announcement), i * 800);
staggerTimers.push(
setTimeout(() => showAnnouncementToast(announcement), i * 800)
);
}
}, 1500);
return () => clearTimeout(timer);
return () => {
clearTimeout(outerTimer);
for (const id of staggerTimers) clearTimeout(id);
};
}, []);
return null;