Skip to content
Back to skills

Rn Animations Gestures

ASecurity

Use when adding animations or gestures to a React Native + Expo app: scale/opacity/translation transitions, layout animations (FadeIn/SlideIn/FadeOut), shared-value driven motion, swipe-to-delete, pan/pinch/long-press gestures, scroll-linked animations. Triggers on: "anima questo", "swipe to X", "fade in/out", "pinch zoom", "scroll-driven animation". Not for: styling (rn-styling), navigation transitions (Expo Router handles those — see rn-expo-router), CSS-only on web (Next.js stack).

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
developmentgoreactnextjsspringapi

Works with

  • api
  • mcp

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add lukedj78/dev-flow --skill rn-animations-gestures --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rn Animations Gestures?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Rn Animations Gestures
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lukedj78-rn-animations-gestures/badge)](https://www.skillsdirectory.com/skills/lukedj78-rn-animations-gestures)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: rn-animations-gestures
description: 'Use when adding animations or gestures to a React Native + Expo app: scale/opacity/translation transitions, layout animations (FadeIn/SlideIn/FadeOut), shared-value driven motion, swipe-to-delete, pan/pinch/long-press gestures, scroll-linked animations. Triggers on: "anima questo", "swipe to X", "fade in/out", "pinch zoom", "scroll-driven animation". Not for: styling (rn-styling), navigation transitions (Expo Router handles those — see rn-expo-router), CSS-only on web (Next.js stack).'
---

# rn-animations-gestures — guardrail for animations + gestures in RN/Expo

> For the current Expo API and per-version details, verify against the Expo docs / MCP `mcp.expo.dev` / `expo/skills` (see rn-fundamentals → Source of truth).

## The 5 rules (non-negotiable)

1. **Reanimated 4 is the default**. Never the legacy `Animated` API from `react-native` for new code. Reanimated 4 also ships a web-style CSS Animations/Transitions API (`transitionProperty` / `transitionDuration` / `transitionTimingFunction` style props, `animationName` keyframes) as a backward-compatible ADDITION to worklets — good for state-driven style changes, not a replacement for `useSharedValue`/`useAnimatedStyle` on gesture-driven motion (see `references/patterns.md`).
2. **Gestures via the Gesture Handler 3 hook API**. Never `PanResponder`. **Expo SDK 58 bundles `react-native-gesture-handler ~3.3.0`** (SDK 57 had `~2.32.0`, a major behind). Use `usePanGesture({...})`, `usePinchGesture`, `useTapGesture`, `useLongPressGesture` with `<GestureDetector>`; compose with `useSimultaneousGestures` / `useCompetingGestures` / `useExclusiveGestures`. ⚠️ The v2 `Gesture.Pan().onEnd(...)` builders still compile in 3.3.0 but every one is `@deprecated` ("will be removed in a future version", `gestureObjects.ts`) — so copied v2 snippets keep working and keep spreading. Callbacks are renamed (`onStart`→`onActivate`, `onEnd`→`onDeactivate`) and a hook gesture cannot relate to a v2 one: migrate a screen whole. Before→after in `references/patterns.md` → "Migrating from Gesture Handler 2".
3. **Worklets run on the UI thread** — they CANNOT access React state directly. To call back to the React Native runtime use **`scheduleOnRN(fn, ...args)` from `react-native-worklets`**. ⚠️ **`runOnJS` is `@deprecated` in Reanimated 4** — still so in `react-native-reanimated@4.7.1`'s own `workletFunctions.ts`, which names the replacement; `runOnUI` → `scheduleOnUI`, `executeOnUIRuntimeSync` → `runOnUISync`, `makeShareableClone` → `createSerializable`. All of them live in `react-native-worklets` (0.13.0 on SDK 58), the package `expo install` already brings alongside Reanimated. The old names still work and will keep compiling, which is why they survive in copied snippets.
4. **Read and write shared values with `.get()` / `.set()`, not `.value`.** Same semantics, but `.value` is the form the React Compiler cannot see through, and `set` takes a functional update: `sv.set(v => v + 1)`. **Never read or write a shared value during render** — a read is a snapshot that never updates and silently desyncs, a write fires mid-reconciliation and is replayed by any re-render you did not cause. Worklets, handlers and effects only.
5. **Never `scheduleOnRN` per frame.** In `onUpdate` or a scroll handler that is 60–120 calls a second across the runtime boundary — the single biggest cause of jank in an RN app, along with `setState` in the same place. It belongs in `onDeactivate`, or in a `useAnimatedReaction` that fires when a value crosses a threshold.
6. **A function called from a worklet needs `'worklet'` as its first line**, or it throws at runtime on device while working fine in the debugger.
7. **Layout animations for enter/exit/move**. Use `entering={FadeIn}`, `exiting={FadeOut}`, `layout={LinearTransition.springify()}` from `react-native-reanimated` — they handle their own worklets correctly. ⚠️ **Reanimated 4.7 (SDK 58) switched them to a new engine by default.** If an enter/exit/layout animation regresses after the upgrade, the rollback is a static flag in `package.json` — `"reanimated": { "staticFeatureFlags": { "USE_LEGACY_LAYOUT_ANIMATIONS_PROXY": true } }` — then a native rebuild; the pod script refuses it alongside `ENABLE_SHARED_ELEMENT_TRANSITIONS` (the legacy proxy has no shared element transitions). A rollback, not a setting to keep.
8. **`useDerivedValue` for computed shared values**. Never `useMemo` on a shared value — `useMemo` runs on JS thread.

## The standards — read before writing motion, and before approving it

**`references/mobile-standards.md`** holds the gate (mobile's own frequency table, where tab switches
never slide), the platform-first tool ladder (`formSheet`, `NativeTabs`, `Link.Preview`,
`headerLargeTitleEnabled` — reach for these before a worklet), the spring configs in Reanimated's
`dampingRatio` form, the `project()` / `rubberband()` worklets, press targets and `hitSlop`, the three
absolute haptics rules, the setup that silently breaks motion, and the **release-build-on-the-slowest-
device** rule. The curves and durations are the same bar as the web's
(`transitions/references/animation-standards.md`); that file is what mobile *changes*.

## Quick decision tree

- "What's the right tool — worklets or the CSS Animations/Transitions API?" → `references/decision-tree.md`
- "How do I structure a worklet-driven animation?" → `references/patterns.md`
- "What native module setup do I need?" → Reanimated 4, `react-native-worklets` and Gesture Handler are all in `rn-bootstrap`'s `install-stack.sh`. No babel config to write: `babel-preset-expo` wires the worklets plugin when the library is installed.

## Common anti-patterns (NEVER do)

- ❌ `import { Animated } from "react-native"` — use `react-native-reanimated`'s `Animated` instead.
- ❌ `setMyState(newValue)` from inside a worklet — `scheduleOnRN(setMyState, newValue)`. And if it is a gesture or scroll handler, prefer a shared value + `useAnimatedStyle` so React never re-renders at all.
- ❌ `runOnJS` / `runOnUI` in new code — deprecated in Reanimated 4 (see rule 3).
- ❌ Reading `props.foo` directly inside `useAnimatedStyle` — capture into a shared value first.
- ❌ `PanResponder` — deprecated for new code. Use `<GestureDetector>`.
- ❌ `Gesture.Pan()` / `Gesture.Simultaneous()` and the other v2 builders in new code — `@deprecated` in Gesture Handler 3 (rule 2).
- ❌ `TouchableOpacity` / `TouchableHighlight` / `TouchableWithoutFeedback` from `react-native-gesture-handler` — `@deprecated` in 3.3.0 ("Use Pressable instead"). Use its `Pressable`, or `Touchable` (`activeScale`, `activeOpacity`, `animationDuration`) for plain press feedback.
- ❌ The old `Swipeable` — gone from Gesture Handler 3. `ReanimatedSwipeable` from `react-native-gesture-handler/ReanimatedSwipeable` (only that and `ReanimatedDrawerLayout/` remain as subpaths). ⚠️ `dragOffsetFromRight` is now **non-positive** (default `-10`; a positive value throws in dev).
- ❌ Installing `react-native-reanimated` alone. **Reanimated 4 moved worklets into `react-native-worklets`**, a separate required package — Expo's own line is `npx expo install react-native-reanimated react-native-worklets`. It builds without it and fails at runtime.
- ❌ Animating `height: 'auto'` — impossible on the UI thread (no measure). Either measure with `onLayout` or use `LayoutAnimation` from Reanimated.
- ❌ Chaining `withTiming(...)` inside `useEffect` without `cancelAnimation` — leaks on unmount.

## Sources

- Course: codewithbeto.dev/rnCourse — "Animations & Gestures" module (paid, distilled).
- Official: https://docs.swmansion.com/react-native-reanimated/docs/
- Official: https://docs.swmansion.com/react-native-gesture-handler/docs/
- Upgrade guide (2 → 3): https://docs.swmansion.com/react-native-gesture-handler/docs/guides/upgrading-to-3

Files in this skill

  • SKILL.md7.8 KB
  • references/decision-tree.md6.4 KB
  • references/mobile-standards.md12.5 KB
  • references/patterns.md14.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.