In Reanimated 4, how do the entering, exiting and layout props animate a view as it mounts, unmounts or changes position?
answer
- props on an Animated component
- FadeIn, SlideInDown, FadeOut presets
- LinearTransition, Layout is deprecated
- builder modifiers: duration, delay, springify
- skipEntering, collapsable={false}
basics
~20 sentering and exiting take preset animations such as FadeInDown or FadeOut that play when an Animated component mounts or unmounts; layout takes a transition such as LinearTransition that animates size and position changes after React re-lays out the view.
solid answer
~40 sLayout animations are props on Reanimated's Animated components. `entering={FadeInDown}` plays when the view is added to the hierarchy, `exiting={FadeOut}` plays when React removes it, with Reanimated keeping the view on screen until the animation ends, and `layout={LinearTransition}` animates the jump when its size or position changes. Presets are builders you customise with modifiers such as `.duration(ms)` (300 by default), `.delay(ms)`, `.springify()` with spring modifiers, and `.withCallback(finished => ...)`; define them outside the component or memoise them. `LayoutAnimationConfig` with `skipEntering` or `skipExiting` suppresses them on a wrapper's mount or unmount, and `Animated.FlatList` takes `itemLayoutAnimation` and `skipEnteringExitingAnimations`. `Layout` is a deprecated alias of `LinearTransition`.
code
tsx · 30 linesimport { Pressable, StyleSheet, Text } from 'react-native';
import Animated, { FadeInDown, FadeOut, LinearTransition } from 'react-native-reanimated';
type Place = { id: string; name: string };
const enter = FadeInDown.duration(250);
const leave = FadeOut.duration(150);
export function NearbyPlaces({ places, onDismiss }: { places: Place[]; onDismiss: (id: string) => void }) {
return (
<Animated.FlatList
data={places}
keyExtractor={(p) => p.id}
itemLayoutAnimation={LinearTransition}
skipEnteringExitingAnimations
renderItem={({ item }) => (
<Animated.View entering={enter} exiting={leave} style={styles.card}>
<Text>{item.name}</Text>
<Pressable accessibilityRole="button" accessibilityLabel={`Dismiss ${item.name}`} onPress={() => onDismiss(item.id)}>
<Text>Dismiss</Text>
</Pressable>
</Animated.View>
)}
/>
);
}
const styles = StyleSheet.create({
card: { padding: 12, marginHorizontal: 16, marginVertical: 4, backgroundColor: 'white' },
});go deeper
Recall the three props, entering, exiting and layout, and name a preset for each, such as FadeInDown, FadeOut and LinearTransition.
Explain how exiting keeps a removed view on screen, how builder modifiers change timing or switch to a spring, and where itemLayoutAnimation and LayoutAnimationConfig fit.
Diagnose exits that never play (flattened parents, overwritten nativeID), avoid a burst of entering animations on first mount, and keep builders out of the render path.
Weigh consistent motion across lists and sheets against cost on low-end devices, and set team conventions for which transitions are allowed where.
## What layout animations are for Most animations change a style while the view stays put. **Layout animations** handle the three moments that `useAnimatedStyle` cannot easily reach, because React changes the tree itself: - a view **appears** (it is mounted), - a view **disappears** (React unmounts it, so there is no component left to animate), - a view **moves or resizes** because its siblings or content changed. Reanimated exposes each as a prop on an Animated component: `entering`, `exiting` and `layout`. In a maps app, the list of nearby places inside the bottom sheet is the classic case: results fade in when a search returns, a dismissed card slides out, and the cards below it glide up instead of jumping. ## `entering` and `exiting` Both props take a **preset** exported from `react-native-reanimated`: | Family | Entering examples | Exiting examples | |---|---|---| | Fade | `FadeIn`, `FadeInDown`, `FadeInUp` | `FadeOut`, `FadeOutDown` | | Slide | `SlideInDown`, `SlideInRight` | `SlideOutDown`, `SlideOutLeft` | | Zoom | `ZoomIn` | `ZoomOut` | - `entering` runs when the Animated component is added to the view hierarchy. - `exiting` runs when React removes it. Reanimated keeps the removed native view on screen while the exit plays, then deletes it. - For shapes the presets do not cover, use a `Keyframe` definition or a custom animation function. ## `layout` `layout={LinearTransition}` tells Reanimated to animate the difference between a view's old and new frame after a layout change, both position and size. Other predefined transitions exist, such as `SequencedTransition`, which animates x-position and width first, then y-position and height. Older code writes `layout={Layout}`; in Reanimated 4 `Layout` is a **deprecated alias** of `LinearTransition`. For lists, `Animated.FlatList` accepts `itemLayoutAnimation={LinearTransition}` and applies the transition to its cells when the items' layout changes, such as after an insert or a removal. ## Customising with modifiers Presets are **builders**: chain modifiers on them. 1. **Timing**: `.duration(ms)` (defaults to 300) and `.easing(fn)` using Reanimated's `Easing`. 2. **Spring**: `.springify()` switches to a spring, then `.damping()`, `.mass()`, `.stiffness()`, or `.duration()` and `.dampingRatio()`. `.easing()` has no effect once `.springify()` is used. 3. **Common**: `.delay(ms)`, `.withCallback(finished => ...)` which reports whether the animation completed uninterrupted, and `.reduceMotion(...)`. Since 4.4, `withInitialValues` and `withTargetValues` override a preset's start and end values; flat transform keys such as `{ translateY: 40 }` are preferred over the deprecated `transform: [...]` tuple there. Create builders **outside the component or inside `useMemo`**; the docs recommend it for performance, because a new builder chain on every render is wasted work. ## Controlling when they run - `LayoutAnimationConfig` wraps a subtree: `skipEntering` skips the children's entering animations when the wrapper mounts, and `skipExiting` skips their exiting animations when it unmounts. Wrappers can be nested to target a smaller part of the tree. - For a list, `Animated.FlatList`'s `skipEnteringExitingAnimations` prop does the same for the list's own mount and unmount, so results already present when the sheet first opens do not all fade in at once. - Animations respect the device's reduced-motion setting through `ReduceMotion`, which other parts of the app own. ## New Architecture gotchas Reanimated's docs list two behaviours specific to the New Architecture, which on React Native 0.87 is the only one: - **`nativeID` is used internally** to configure entering animations. A parent that overwrites its children's `nativeID` can stop them from running; wrapping the animated child in a `View` works around it. - **View flattening**: if a plain, non-animated parent is removed, its children's exiting animations start, but the parent does not wait for them, so they vanish early. Set `collapsable={false}` on that parent to keep it as a real native view. ## Interview traps - **"React already removed it, so exiting can't work."** It can: the component is gone from React's tree, but Reanimated holds on to the native view until the exit animation finishes. - **Using `Layout` in new code.** It still compiles, but it is a deprecated alias; write `LinearTransition`. - **Putting layout props on a plain `View`.** `entering`, `exiting` and `layout` are props of Reanimated's Animated components, such as `Animated.View`, not of core `View`. - **Chaining `.easing()` after `.springify()`.** It is silently ignored; a spring's shape comes from its spring modifiers. ## When to use them instead of `useAnimatedStyle` | Situation | Better tool | |---|---| | A card appears or is dismissed | `entering` / `exiting` | | Siblings move after an insert or removal | `layout` or `itemLayoutAnimation` | | A value follows a finger or a scroll | Shared value plus `useAnimatedStyle` |
- A card with exiting={FadeOut} disappears instantly when its plain View wrapper is removed. Why, and what fixes it?On the New Architecture a non-animated parent that gets removed does not wait for its children's exiting animations, because of view flattening. Setting `collapsable={false}` on the parent keeps it as a real native view so the children's exits can finish.
- Why should layout animation builders be created at module scope or in useMemo rather than inline in render?A chain like `FadeInDown.duration(250).delay(50)` builds a new configuration object each time it is evaluated. Created inline, it is rebuilt on every render; Reanimated's docs recommend defining builders outside the component or memoising them for performance.
exiting is a theatre curtain call: the actor has been written out of the script, but stays on stage to take a bow before the stage manager clears them.
saying these in an interview costs you the question
- exiting animations cannot work because React has already removed the component.
- Layout is the current name for the linear transition in Reanimated 4.
- entering and exiting work on a plain View imported from react-native.
- LayoutAnimationConfig with skipEntering disables every layout transition in its subtree forever.
- .easing() still shapes a transition after .springify() has been called.