name: framer-motion description: >- Framer Motion / Motion for React patterns. Use when adding or debugging animation in React components that import from 'framer-motion' or 'motion/react' — motion.* elements, initial/animate/exit, AnimatePresence, layout/spring transitions — and especially when an animation re-fires, flickers, or fails to play because of React key / identity changes.
framer-motion
The one concept that causes most Framer Motion bugs: animations are driven
by React identity (the key), not by prop values.
Version & import (check before editing)
'framer-motion'(v10 through v13, still published) and'motion/react'(themotionpackage from 11.11.12 on, which wraps the same library) expose the samemotion/AnimatePresenceAPI:import { motion, AnimatePresence } from 'framer-motion'orfrom 'motion/react'.- Match the repo's existing import path and pin; never mix the two paths unless deliberately doing a version bump. (Verified against npm 2026-09-03.)
The mental model: keys drive animation
Framer Motion animates a motion.* component when React mounts it
(initial → animate) and when React unmounts it inside an
<AnimatePresence> (animate → exit). React decides mount/unmount by the
element's key (identity), not by whether its props changed.
Canonical write-up, for reference: https://www.nan.fyi/keys-in-framer-motion
Consequences you will hit:
- Same key, changed props → no
initial/exit; the existing element tweens toward the newanimatetarget. This is what you want for "value updated, animate to it." - Changed key → React unmounts the old element and mounts a fresh one →
exittheninitialfire. This is how you intentionally replay an entrance animation (e.g. remount on a counter). - Accidentally-unstable key → the entrance animation re-fires on every render that produces a "new" element → flicker. In a list this looks like items popping/fading repeatedly.
Canvas libraries (React Flow and kin)
React Flow keys nodes/edges by id, so the id is the animation identity:
stable ids keep inner motion.* elements mounted (no replayed initial); a
changed id remounts the node and re-fires its entrance. If entrances flicker on
a canvas, find what is changing identity — ids, or node/edge objects rebuilt
with new references every render — and stabilize it; initial={false} only
hides the symptom.
Idioms
- Entrance =
initialopacity/scale →animateto{opacity:1, scale:1}, spring on scale. - "Don't animate on first paint" =
initial={false}on themotionelement or on<AnimatePresence>. - Enter/exit of list items = wrap in
<AnimatePresence>; usemode="popLayout"when siblings should reflow as one leaves.
AnimatePresence gotchas
- Direct children of
<AnimatePresence>must each have a stable, uniquekeyand must be the conditionally-rendered element itself. A wrapper that's always mounted defeatsexit. exitonly runs for elements removed while still inside an<AnimatePresence>that stays mounted. Unmounting theAnimatePresenceitself skips exit animations.mode="popLayout"pops the exiting element out of layout flow so the rest reflow immediately — good for vertical stacks, can look wrong for grids.
Quick checklist when an animation misbehaves
- Re-fires/flickers? The key changed when it shouldn't. Find the
key(for canvas nodes, theid) or the identity-equality gap. Stabilize identity, don't addinitial={false}to mask it. - Won't replay when you want it to? The key is too stable — change it intentionally to remount.
exitnever plays? Element isn't a keyed direct child of a persistent<AnimatePresence>.- Animating the wrong thing? Check which system owns the property first —
a canvas library may position or tween nodes itself, leaving Framer Motion
only enter/exit/scale/opacity — before adding
motionprops for it.
Related skills
react-flow-v12— the@xyflow/reactAPI (keys = node/edgeid).
