Diagnosing Missing Exit Animations in Framer Motion with AnimatePresence
Learn why Framer Motion exit animations may not run and how to diagnose missing AnimatePresence, incorrect mode, missing exit prop, or key issues.
03 Mar 2026, 09:42 UTC

Problem: Exit animations do not run when a component unmounts
You notice that when a component is removed from the DOM (for example, by changing its key or toggling a visibility flag), it disappears instantly instead of fading, sliding, or scaling out as defined by an exit prop on a motion element.
Recognizable condition
The component mounts and its entrance animation works, but on unmount there is no visible transition; the element is removed from the DOM immediately after the render cycle.
Cause / diagnostic table
| Possible cause | What to look for |
|---|---|
AnimatePresence wrapper missing | The unmounting component is not wrapped by AnimatePresence anywhere in the tree. |
mode prop not set or set incorrectly | The wrapper exists but mode is omitted or set to a value that prevents waiting for exit (e.g., mode\'pop\' when you need waiting). |
exit prop undefined on the motion element | The motion component lacks an exit object, so Framer Motion has nothing to animate. |
| Key does not change on unmount | The component’s key stays the same across renders, so React does not treat it as a remount and AnimatePresence sees no exit opportunity. |
CSS overrides (e.g., display: none or height:0) applied during exit | Styles from CSS or inline styles conflict with the animated values, causing the element to be hidden before the animation can run. |
Ordered checks
- Verify the component tree: locate the component that should exit and check whether it is rendered inside an
<AnimatePresence>element. Use React DevTools to highlight the wrapper. - Inspect the
AnimatePresenceprops: confirm that amodeprop is present. If omitted, the default ismode\'sync\'; for waiting until all exit animations finish, you needmode\'wait\'. - Check the motion element: ensure it receives an
exitprop (e.g.,exit={{opacity:0, scale:0.95}}). Look at the element’s props in the DevTools console. - Confirm that the component’s key changes when it should unmount. In DevTools, toggle the condition that removes the component and watch the key attribute change.
- Look for conflicting CSS: in the Elements panel, see if any rule sets
display:none,height:0, or overridesopacity/transformduring the exit period.
Fixes tied to findings
- Add the wrapper if missing:
import { AnimatePresence, motion } from 'framer-motion'; function List({ items }) { return ( {items.map(item => ( {item.label} ))} ); } - Set or correct the
modeprop: usemode\'wait\'when you need the parent to wait for all exiting children to finish their animations before removing them from the DOM. - Define an
exitobject on each motion element that matches the visual effect you want (opacity, scale, translate, etc.). - Ensure the component’s key changes on unmount. If you are conditionally rendering, key the element with a value that changes when the condition flips (e.g.,
key={item.id}orkey={show ? 'shown' : 'hidden'}). - Remove or adjust CSS that interferes: avoid
display:noneon the exiting element; instead rely on Framer Motion’s animated values to hide it.
Escalation criteria
If after applying the above fixes the exit animation still does not appear:
- Check for nested
AnimatePresencecomponents that might be swallowing the exit signal; ensure only the nearest wrapper handles the exit. - Verify that no parent element has
overflow:hiddenor a clipping mask that hides the animated element before the transition completes. - Confirm that the version of Framer Motion in use supports the
exitprop (versions >=2.0.0). Older releases required theexitprop to be passed via thecustomattribute; consult the migration guide if you are on a pre‑2.0 release. - As a last resort, isolate the motion element in a minimal sandbox (e.g., a separate CodeSandbox) with only
AnimatePresenceand the motion element to rule out interference from other libraries or global CSS.
Example configuration
The following snippet shows a before/after scenario for a simple toast notification that should fade out when dismissed.
// Before: exit animation missing
import { motion } from 'framer-motion';
function Toast({ show }) {
if (!show) return null;
return (
instant removal
>
Toast message
);
}
// After: added AnimatePresence and exit
import { AnimatePresence, motion } from 'framer-motion';
function Toast({ show }) {
return (
{show && (
Toast message
)}
);
}
Limitations and practical verification
This guide assumes that the component’s unmount is triggered by a key change or conditional rendering. If the component is removed via a CSS animation that sets display:none before the React unmount, Framer Motion cannot intervene; you must remove such CSS.
To verify the fix:
- Render the component in isolation.
- Open React DevTools, select the exiting motion element, and toggle the condition that causes it to unmount.
- In the Elements panel, watch the
styleattribute: you should see the values defined inexitbeing applied over time (e.g., opacity decreasing from 1 to 0). - Confirm that the element remains in the DOM until the transition completes (the node is not removed immediately).
If the element disappears before the animated values finish, re‑check for conflicting CSS or an incorrect mode setting.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.