perf: move update card timer cleanup to ref (#4093)

This commit is contained in:
Neil
2026-05-31 04:05:11 -07:00
committed by GitHub
parent 3065c1a5b6
commit 4cdbb261fc
+22 -9
View File
@@ -1,7 +1,7 @@
/* eslint-disable max-lines -- Why: the update card owns the full updater lifecycle in one
renderer surface. Keeping the state machine and its presentation variants together avoids
scattering tightly coupled update behavior across multiple files. */
import { useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { usePrefersReducedMotion } from '@/hooks/usePrefersReducedMotion'
import { useAppStore } from '../store'
import { Card } from './ui/card'
@@ -200,17 +200,29 @@ export function UpdateCard() {
// ── Prefers-reduced-motion ──────────────────────────────────────────
const prefersReducedMotion = usePrefersReducedMotion()
useEffect(() => {
return () => {
if (dismissAnimationTimerRef.current !== null) {
window.clearTimeout(dismissAnimationTimerRef.current)
}
if (collapseAnimationTimerRef.current !== null) {
window.clearTimeout(collapseAnimationTimerRef.current)
}
const clearAnimationTimers = useCallback(() => {
if (dismissAnimationTimerRef.current !== null) {
window.clearTimeout(dismissAnimationTimerRef.current)
dismissAnimationTimerRef.current = null
}
if (collapseAnimationTimerRef.current !== null) {
window.clearTimeout(collapseAnimationTimerRef.current)
collapseAnimationTimerRef.current = null
}
}, [])
const cardRootRef = useCallback(
(node: HTMLDivElement | null) => {
if (node !== null) {
return
}
// Why: exit timers are owned by the visible update-card surface, so
// stale callbacks should be cancelled as soon as that surface unmounts.
clearAnimationTimers()
},
[clearAnimationTimers]
)
// ── Visibility gates ──────────────────────────────────────────────
const isUserInitiated = 'userInitiated' in status && status.userInitiated
@@ -542,6 +554,7 @@ export function UpdateCard() {
return (
<div
ref={cardRootRef}
className="fixed bottom-10 right-4 z-40 w-[360px] max-w-[calc(100vw-32px)] flex flex-col gap-2
max-[480px]:left-4 max-[480px]:right-4 max-[480px]:w-auto"
>