Skip to main content
Motion & React5 min readNovember 2026

Why is my AnimatePresence exit animation not working?

Short answer

Exit animations only run when AnimatePresence stays mounted and its direct child is removed. The usual causes are: the condition is outside AnimatePresence, the child has no unique key, the exit prop is on a nested element, or a parent unmounts too. For route transitions, key the routes by location and use mode="wait".

Core Takeaway

  • AnimatePresence must stay mounted; put the condition inside it
  • The direct child needs the exit prop and a unique key
  • Use mode="wait" to finish the exit before the next enter
  • For React Router, key the routes with location.pathname
  • State that changes very fast is a known edge case; update Motion

This is one of the most viewed Motion questions on Stack Overflow, and two of the most discussed GitHub issues are about AnimatePresence getting stuck when state changes quickly.

1. Put the condition inside AnimatePresence

// wrong: AnimatePresence unmounts with the modal
{isOpen && (
  <AnimatePresence>
    <motion.div exit={{ opacity: 0 }} />
  </AnimatePresence>
)}

// right
<AnimatePresence>
  {isOpen && <motion.div key="modal" exit={{ opacity: 0 }} />}
</AnimatePresence>

2. Give each child a unique key

When you swap one child for another, AnimatePresence tells them apart by key. Without a key, or with the array index, it cannot detect that the old one left.

3. Put exit on the direct child

The exit prop must be on the motion component that AnimatePresence sees as its child. If you wrap it in your own component, that component must render a motion element at the top and pass props down.

4. Route transitions

const location = useLocation();
<AnimatePresence mode="wait">
  <Routes location={location} key={location.pathname}>
    ...
  </Routes>
</AnimatePresence>

5. Fast state changes

If users click faster than the exit takes, older versions could leave elements stuck. Update to the latest motion package first. Using mode="wait" or shorter exits also helps.

6. Next.js App Router

The App Router swaps layouts in ways that make page exit animations hard. Animate inside the page, or look at the View Transitions API.

Frequently asked questions

Why does my exit animation flash and disappear?

The element was removed by a parent that unmounted at the same time. Keep AnimatePresence above the condition.

What does mode="wait" do?

It waits for the exiting child to finish before the entering child animates in.

How do I run code after an exit finishes?

Pass onExitComplete to AnimatePresence.

Can I animate a list item being removed?

Yes. Wrap the mapped list in AnimatePresence and give each item a stable key, not its index.

Related Guides & Examples

States instead of mount and unmount

In ExodeUI, enter and exit are transitions in a state machine, so nothing gets stuck mid-unmount.

Learn about state machines
ExodeUI

EXODEUI DESKTOP

A little space for good ideas.

Choose your platform to get the official ExodeUI installer.

Looking for Intel Mac or other builds? Explore the web studio or check all download options.

Prefer the browser? Try for free in your browser →