Skip to content

perf(shimmer): cancel ShimmerView repeat animation on unmount - #1798

Open
f-liva wants to merge 1 commit into
slopus:mainfrom
f-liva:perf/shimmerview-cancel-animation
Open

f-liva wants to merge 1 commit into
slopus:mainfrom
f-liva:perf/shimmerview-cancel-animation

Conversation

@f-liva

@f-liva f-liva commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Problem

ShimmerView kicks off an infinite withRepeat sweep in a useEffect but never cancels it. When the component unmounts, the animation driver stays live and — through useAnimatedStyle — keeps the Animated gradient and its MaskedView subtree referenced.

On web that MaskedView renders as an <svg> mask, so every unmounted shimmer leaks a detached SVG tree and pins an animation driver. On a long-lived tab this grows the heap.

Diagnosed on happy.federicoliva.it (self-host web) via heap-snapshot diff: detached SVG objects (SVGAnimatedLength, SVGAnimatedTransformList, blink::SMILTimeContainer, SVGSVGElement) retained by the reanimated animation-driver closure scope (system / Context / scope).

Same class of bug as the StatusDot pulse (#1796). ShimmerText already cancels on unmount; ShimmerView was the one left.

Fix

Return a cleanup from the effect that calls cancelAnimation(shimmerTranslate) on unmount, so the driver stops and the gradient/mask subtree can be collected.

Part of the perf work in #1765.

🤖 Generated with Claude Code

ShimmerView started an infinite withRepeat sweep in an effect but never
cancelled it. When the component unmounts the animation driver stays live and,
through useAnimatedStyle, keeps the Animated gradient and its MaskedView subtree
referenced. On web that subtree renders as an <svg> mask, so every unmounted
shimmer leaks a detached SVG tree (SVGAnimatedLength/TransformList/
SMILTimeContainer seen retained by the animation-driver closure scope in
heap-snapshot diffs) and pins an animation driver — the heap grows the longer
the tab lives.

Add the cleanup to stop the repeat on unmount, matching StatusDot and
ShimmerText (which already cancel on unmount).

Refs slopus#1765.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant