skip to content

In Reanimated 4, how do the entering, exiting and layout props animate a view as it mounts, unmounts or changes position?

level: middleimportance: should knowfreq 32%

answer

  1. props on an Animated component
  2. FadeIn, SlideInDown, FadeOut presets
  3. LinearTransition, Layout is deprecated
  4. builder modifiers: duration, delay, springify
  5. skipEntering, collapsable={false}

basics

~20 s

entering 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 s

Layout 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 lines
tsx
import { 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

for a junior

Recall the three props, entering, exiting and layout, and name a preset for each, such as FadeInDown, FadeOut and LinearTransition.

for a middle

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.

for a senior

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.

for a principal

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.