Motion
Back to framer.com
DocumentationComponents
AnimatePresence
Motion
Back to framer.com
Design and publish your first free site today.
Getting started
  • Introduction
  • Examples
Animation
  • Overview
  • Layout
  • Gestures
  • Scroll
  • Transition
Components
  • motion
  • AnimatePresence
  • LayoutGroup
  • LazyMotion
  • MotionConfig
  • Reorder
Motion values
  • Overview
  • useMotionValueEvent
  • useMotionTemplate
  • useScroll
  • useSpring
  • useTime
  • useTransform
  • useVelocity
  • useWillChange
Utilities
  • animate
  • transform
  • useAnimationControls
  • useAnimationFrame
  • useDragControls
  • useInView
  • useReducedMotion
3D
  • Introduction
  • LayoutCamera
  • LayoutOrthographicCamera
  • MotionCanvas
Guides
  • Accessibility
  • Reduce bundle size
  • Upgrade guides
Community
  • GitHub
  • Discord

AnimatePresence

Animate components when they're removed from the React tree.

AnimatePresence allows components to animate out when they're removed from the React tree.

It's required to enable exit animations because React lacks a lifecycle method that:

  1. Notifies components when they're going to be unmounted and
  2. Allows them to defer that unmounting until after an operation is complete (for instance an animation).
import { motion, AnimatePresence } from "framer-motion"
export const MyComponent = ({ isVisible }) => (
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>
)

#Usage

#Exit animations

AnimatePresence works by detecting when direct children are removed from the React tree.

Any motion components contained by the removed child that have an exit prop will fire that animation before the entire tree is finally removed from the DOM.

Note: Direct children must each have a unique key prop so AnimatePresence can track their presence in the tree.

const MyComponent = ({ isVisible }) => (
<AnimatePresence>
{isVisible && (
<motion.div
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>
)

Like initial and animate, exit can be defined either as a TargetAndTransition object of values, or a variant label to animate out a whole tree.

In React, changing a component's key makes React treat it as an entirely new component. So the old one is unmounted before the new one is mounted. So by changing the key of a single child of AnimatePresence, we can easily make components like slideshows.

export const Slideshow = ({ image }) => (
<AnimatePresence>
<motion.img
key={image.src}
src={image.src}
initial={{ x: 300, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
exit={{ x: -300, opacity: 0 }}
/>
</AnimatePresence>
)

#Multiple children

AnimatePresence works the same way with multiple children. Just ensure that each has a unique key and components will animate in and out as they're added or removed from the tree.

export const Notifications = ({ messages }) => (
<AnimatePresence>
{messages.map(({ id, content }) => (
<motion.li
key={id}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{content}
</motion.li>
))}
</AnimatePresence>
)

#Suppressing initial animations

Mount animations are already handled by motion components via the initial and animate props.

If a motion component is set to initial={false}, it'll start in the state defined in animate. But sometimes, for instance a chatbox or a slideshow, we only want to animate in new components, that are added after the initial render.

By setting initial={false} on AnimatePresence, components present when AnimatePresence first loads will start in their animate state. Only components that enter after this initial render will animate in.

const MyComponent = ({ isVisible }) => (
<AnimatePresence initial={false}>
{isVisible && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>
)

#Animating custom components

The children of AnimatePresence can also be custom components. The only requirement is that somewhere within this component is at least one motion component with an exit prop.

Note: The custom component being removed from the DOM must still be a direct descendant of AnimatePresence for the exit animation(s) it contains to trigger.

const Item = () => (
<div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
</div>
)
/**
* The component being removed must be a direct
* descendant of AnimatePresence due to limitations
* with React.
*/
export const MyComponent = ({ items }) => (
<AnimatePresence>
{items.map(({ id }) => (
<Item key={id} />
))}
</AnimatePresence>
)

#Props

#initial: boolean

By passing initial={false}, AnimatePresence will disable any initial animations on children that are present when the component is first rendered.

<AnimatePresence initial={false}>
{isVisible && (
<motion.div
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>

#custom: any

When a component is removed, there's no longer a chance to update its props. So if a component's exit prop is defined as a dynamic variant and you want to pass a new custom prop, you can do so via AnimatePresence. This will ensure all leaving components animate using the latest data.

#mode: "sync" | "wait" | "popLayout"

Decides how AnimatePresence handles entering and exiting children.

  • "sync": (Default) Children animate in/out as soon as they're added/removed.
  • "wait": The entering child will wait until the exiting child has animated out. Note: Currently only renders a single child at a time.
  • "popLayout": Exiting children will be "popped" out of the page layout. This allows surrounding elements to move to their new layout immediately.

Custom component note: When using popLayout mode, any immediate child of AnimatePresence that's a custom component must be wrapped in React's forwardRef function, forwarding the provided ref to the DOM node you wish to pop out of the layout.

#onExitComplete(): void

Fires when all exiting nodes have completed animating out.

#usePresence

#usePresence(): AlwaysPresent | Present | NotPresent

When a component is the child of AnimatePresence, it can use usePresence to access information about whether it's still present in the React tree.

If isPresent is false, it means that a component has been removed the tree, but AnimatePresence won't really remove it until safeToRemove has been called.

import { usePresence } from "framer-motion"
export const Component = () => {
const [isPresent, safeToRemove] = usePresence()
useEffect(() => {
!isPresent && setTimeout(safeToRemove, 1000)
}, [isPresent])
return <div />
}

#useIsPresent

#useIsPresent(): boolean

Similar to usePresence, except useIsPresent simply returns whether or not the component is present. There is no safeToRemove function.

import { useIsPresent } from "framer-motion"
export const Component = () => {
const isPresent = useIsPresent()
useEffect(() => {
!isPresent && console.log("I've been removed!")
}, [isPresent])
return <div />
}
PreviousMotion componentsNextLayoutGroup
On this page
  • Usage
  • Exit animations
  • Multiple children
  • Suppressing initial animations
  • Animating custom components
  • Props
  • usePresence
  • useIsPresent

Copyright © 2022 Framer B.V.

  • Security
  • Terms of Service
  • Privacy Statement