Prompt
Use react-native-reanimated to create a pulsing circle animation. The circle should scale between 1x and 1.5x continuously — and the animation must be cancelled when the component unmounts.
Solution
The point of Reanimated here is where the work runs: the shared value and the useAnimatedStyle worklet live on the UI thread, so the pulse stays at frame rate even when the JS thread is busy — a setState-driven animation would push sixty re-renders a second through React and stutter under any real load.
Composition is the mechanic to narrate: withTiming(1.5, { duration: 1000 }) describes one leg, withRepeat(…, -1, true) wraps it — -1 means forever, true means reverse each iteration, which is what makes it a smooth 1 → 1.5 → 1 pulse instead of snapping back to 1 every cycle.
Two senior details. First, cancelAnimation in the effect cleanup: an infinite animation nobody cancels keeps ticking after unmount — the same slow-leak family as an uncancelled interval, and the kind of thing that only shows up as battery drain and memory growth in production. Second, the property choice: transform: scale is composited without recomputing layout; animating width/height to fake the same pulse forces layout every frame.
Red flag: reading or writing scale.value in the render body. Renders don't subscribe to shared values — the binding must live inside the useAnimatedStyle worklet, and mutation belongs in effects or gesture callbacks.
Say it: "I animate transform scale on the UI thread with withRepeat and reverse, and I cancel it in the effect cleanup — an uncancelled infinite animation is a leak that outlives the component."