home / skills / sovranbitcoin / sovran / animation-performance
This skill helps you optimize React Native animation performance using Reanimated, worklets, and gesture handlers for buttery 60fps animations.
npx playbooks add skill sovranbitcoin/sovran --skill animation-performanceReview the files below or copy the command above to add this skill to your agents.
---
name: animation-performance
description: Provides React Native Reanimated, React Native Worklets, React Native Gesture Handler performance optimization guidelines for smooth animations. Applies to tasks involving shared values, worklets, frame callbacks, gesture handlers, animated styles, re-renders, or debugging animation jank and frame drops.
---
# Animation Performance Tips
## Overview
Performance optimization guide for React Native Reanimated animations, covering shared values, worklets, memoization, and rendering optimizations. These guidelines ensure buttery smooth animations at 60fps.
## When to Apply
Reference these guidelines when:
- Debugging janky or stuttering animations
- Optimizing animation performance (FPS drops)
- Working with shared values and worklets
- Implementing gesture handlers
- Optimizing animated lists and scroll handlers
- Reviewing Reanimated code for performance issues
## Priority-Ordered Guidelines
| Priority | Category | Impact | Prefix |
|----------|----------|--------|--------|
| 1 | Shared Values Usage | CRITICAL | `shared-values-*` |
| 2 | Re-renders | CRITICAL | `re-renders-*` |
| 3 | Memoization | HIGH | `memoization-*` |
| 4 | Animation Calculations | HIGH | `calculations-*` |
| 5 | Layout vs Transform | HIGH | `layout-*` |
| 6 | Reactions | HIGH | `reactions-*` |
| 7 | Hooks Selection | HIGH | `hooks-*` |
| 8 | Animation Lifecycle | MEDIUM | `animations-*` |
| 9 | Component Limits | MEDIUM | `limits-*` |
| 10 | Scroll Optimization | MEDIUM | `scroll-*` |
## Quick Reference
### Critical: Shared Values Usage
**Common mistakes:**
- Reading shared values on JS thread (causes thread blocking)
- Accessing shared values during render (violates Rules of React)
- Using component state for animation values (triggers re-renders)
**Quick fixes:**
- Read shared values only in worklets (`useAnimatedStyle`, `useDerivedValue`) - see `shared-values-read-in-worklets.md`
- Access shared values in `useEffect` or callbacks, not during render - see `shared-values-during-render.md`
- Use `useSharedValue` instead of `useState` for animation values - see `re-renders-use-shared-values.md`
- Track animation state with `useRef` instead of reading shared values - see `shared-values-track-state-with-ref.md`
- Initialize with simple values, compute complex ones in worklets - see `shared-values-initialization.md`
### Critical: Re-renders
**Common fixes:**
- Use shared values instead of component state for animations
- Memoize animation objects outside component or with constants
- Memoize frame callbacks with `useCallback`
- Memoize gesture objects with `useMemo`
### High: Animation Calculations
**Common fixes:**
- Use `useDerivedValue` for expensive calculations - see `calculations-use-derived-value.md`
- Avoid conditional logic in worklets - see `calculations-avoid-conditionals.md`
- Use `clamp` instead of manual Math.min/max - see `calculations-use-clamp.md`
- Batch updates with `scheduleOnUI` - see `calculations-batch-with-schedule-on-ui.md`
- Prefer transform properties over layout properties - see `layout-prefer-transform.md`
- Choose the right hook (`useAnimatedProps` vs `useAnimatedStyle`) - see `hooks-choose-animated-props.md`
- Optimize `useAnimatedReaction` dependencies - see `reactions-optimize-dependencies.md`
- Cancel animations properly before starting new ones - see `animations-cancel-properly.md`
## References
Full documentation with code examples in `references/`:
### Shared Values (`shared-values-*`)
| File | Impact | Description |
|------|--------|-------------|
| `shared-values-read-in-worklets.md` | CRITICAL | Read shared values only in worklets, not on JS thread |
| `shared-values-during-render.md` | CRITICAL | Don't read/modify shared values during render |
| `shared-values-track-state-with-ref.md` | HIGH | Track animation state with useRef instead of reading shared values |
| `shared-values-initialization.md` | HIGH | Avoid expensive initial values, use simple primitives |
### Re-renders (`re-renders-*`)
| File | Impact | Description |
|------|--------|-------------|
| `re-renders-use-shared-values.md` | CRITICAL | Use shared values instead of component state for animations |
### Memoization (`memoization-*`)
| File | Impact | Description |
|------|--------|-------------|
| `memoization-animations.md` | HIGH | Memoize animation objects to prevent recreation |
| `memoization-frame-callbacks.md` | HIGH | Memoize frame callbacks with useCallback |
| `memoization-gesture-objects.md` | HIGH | Memoize gesture objects with useMemo |
### Calculations (`calculations-*`)
| File | Impact | Description |
|------|--------|-------------|
| `calculations-use-derived-value.md` | HIGH | Use useDerivedValue to optimize useAnimatedStyle calculations |
| `calculations-avoid-conditionals.md` | HIGH | Minimize conditional logic in worklets, use useDerivedValue |
| `calculations-use-clamp.md` | HIGH | Use clamp instead of manual Math.min/max in worklets |
| `calculations-batch-with-schedule-on-ui.md` | HIGH | Batch shared value updates with scheduleOnUI |
### Layout (`layout-*`)
| File | Impact | Description |
|------|--------|-------------|
| `layout-prefer-transform.md` | HIGH | Prefer transform over layout properties |
### Reactions (`reactions-*`)
| File | Impact | Description |
|------|--------|-------------|
| `reactions-optimize-dependencies.md` | HIGH | Avoid unnecessary reactions, optimize dependency tracking |
### Hooks (`hooks-*`)
| File | Impact | Description |
|------|--------|-------------|
| `hooks-choose-animated-props.md` | HIGH | Choose useAnimatedProps vs useAnimatedStyle correctly |
### Animations (`animations-*`)
| File | Impact | Description |
|------|--------|-------------|
| `animations-cancel-properly.md` | MEDIUM | Cancel running animations before starting new ones |
### Limits (`limits-*`)
| File | Impact | Description |
|------|--------|-------------|
| `limits-animated-components.md` | MEDIUM | Limit number of simultaneously animated components |
### Scroll (`scroll-*`)
| File | Impact | Description |
|------|--------|-------------|
| `scroll-handlers-throttle.md` | MEDIUM | Optimize scroll handlers with throttling |
## Problem → Skill Mapping
| Problem | Start With |
|---------|------------|
| Animation feels janky/stuttering | `shared-values-read-in-worklets.md` → `re-renders-use-shared-values.md` |
| Reading shared value to determine toggle state | `shared-values-track-state-with-ref.md` |
| Too many re-renders during animation | `re-renders-use-shared-values.md` → `memoization-animations.md` |
| Expensive calculations every frame | `calculations-use-derived-value.md` → `calculations-avoid-conditionals.md` |
| Conditional logic in worklets causing jank | `calculations-avoid-conditionals.md` |
| Layout animations are slow | `layout-prefer-transform.md` |
| Multiple shared value updates cause jank | `calculations-batch-with-schedule-on-ui.md` |
| Clamping values inefficiently | `calculations-use-clamp.md` |
| Frame callback performance issues | `memoization-frame-callbacks.md` |
| Gesture handler reattaches frequently | `memoization-gesture-objects.md` |
| useAnimatedReaction causing performance issues | `reactions-optimize-dependencies.md` |
| Wrong hook choice (useAnimatedProps vs useAnimatedStyle) | `hooks-choose-animated-props.md` |
| Animations conflicting or not canceling | `animations-cancel-properly.md` |
| Shared value initialization is expensive | `shared-values-initialization.md` |
| Too many animated components | `limits-animated-components.md` |
| Scroll handler causes performance issues | `scroll-handlers-throttle.md` |
This skill provides focused performance guidelines for React Native Reanimated, Worklets, and Gesture Handler usage to achieve smooth, 60fps animations in mobile apps. It targets common sources of jank such as shared-value misuse, unnecessary re-renders, expensive per-frame calculations, and misconfigured gesture handlers. The guidance is practical and prioritized so you can find high-impact fixes quickly.
The skill inspects common animation patterns and recommends targeted changes: move animation state to useSharedValue, keep heavy logic on the UI thread inside worklets, and prefer transforms over layout updates. It highlights memoization points (gesture objects, frame callbacks, animation objects), useDerivedValue for expensive calculations, and batching updates with scheduleOnUI. It also points out lifecycle and cancellation best practices to avoid competing animations and leaks.
Why should I avoid reading shared values during render?
Reading shared values during render forces JS thread interaction and can break the Rules of React; keep reads inside worklets or effects to prevent blocking and extra renders.
When should I use useDerivedValue vs useAnimatedStyle?
Use useDerivedValue for expensive or repeated calculations and then reference that derived value inside useAnimatedStyle to reduce per-style computation.