In React Native, what does LayoutAnimation.configureNext do, and is UIManager.setLayoutAnimationEnabledExperimental still needed on Android in 0.87?
answer
- call it before the state change
- animates the next layout commit
- create, update and delete configs
- presets: easeInEaseOut, linear, spring
- the Android flag is a no-op now
basics
~20 sLayoutAnimation.configureNext, called just before a state change, animates every layout change in the next commit: views created, moved, resized or removed. Under the New Architecture, the only architecture since 0.82, UIManager.setLayoutAnimationEnabledExperimental is a no-op that only logs a warning.
solid answer
~50 s`LayoutAnimation.configureNext(config)` tells React Native to animate the next layout pass. You call it right before `setState`, and every view that the resulting commit creates, moves, resizes or deletes animates from its old layout to its new one, without animating any value yourself. The config has a `duration` and separate `create`, `update` and `delete` entries with a `type` (such as `easeInEaseOut`, `linear` or `spring`) and, for create and delete, a `property` such as `opacity` or `scaleXY`. Presets cover the common cases: `easeInEaseOut` (300 ms), `linear` (500 ms) and `spring` (700 ms). The old Android snippet calling `UIManager.setLayoutAnimationEnabledExperimental(true)` is still in the docs, but in the New Architecture it is a no-op that only warns in development. The trade-offs: it applies to the whole commit rather than one view, and it cannot be interrupted or driven like an `Animated` value.
code
tsx · 31 linesimport {useState} from 'react';
import {LayoutAnimation, Pressable, StyleSheet, Text, View} from 'react-native';
export function LikeRow({initialCount}: {initialCount: number}) {
const [count, setCount] = useState(initialCount);
const [liked, setLiked] = useState(false);
const toggle = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setLiked(prev => !prev);
setCount(c => (liked ? c - 1 : c + 1));
};
return (
<View>
<View style={styles.row}>
<Pressable onPress={toggle} accessibilityRole="button">
<Text style={styles.heart}>{liked ? '\u2665' : '\u2661'}</Text>
</Pressable>
<Text>{count.toLocaleString()}</Text>
</View>
{liked && <Text style={styles.note}>You and {count - 1} others</Text>}
</View>
);
}
const styles = StyleSheet.create({
row: {flexDirection: 'row', alignItems: 'center', gap: 8},
heart: {fontSize: 28},
note: {color: 'gray'},
});go deeper
Recall the call order, configureNext then setState, and the three presets.
Explain the create, update and delete config and that the Android enable flag is a no-op under the New Architecture.
Judge when a whole-commit, fire-and-forget layout animation is acceptable, and spot unrelated views animating by accident.
Decide the app's approach to layout motion, LayoutAnimation, JS-driven Animated or the experimental backend, and its consistency across screens.
## What LayoutAnimation does Most animations move a value. `LayoutAnimation` animates **layout itself**: the positions and sizes that Yoga computes. You do not create values or bind styles. You say "animate whatever changes in the next layout", and then change state: 1. Call `LayoutAnimation.configureNext(config)`. 2. Call `setState` (or otherwise trigger a re-render) that changes layout. 3. When that commit is mounted, each view animates from its old frame to its new one; views that appear or disappear use the `create` and `delete` settings. ## The configuration | Field | Meaning | |---|---| | `duration` | length of the animation in ms | | `create` | how newly inserted views appear: `type`, and a `property` such as `opacity`, `scaleX`, `scaleY` or `scaleXY` | | `update` | how existing views move or resize: `type`, optionally `springDamping` for springs | | `delete` | how removed views disappear: `type` and `property` | `LayoutAnimation.create(duration, type, property)` builds such a config, and three **presets** exist, each also available as a shortcut method: - `LayoutAnimation.Presets.easeInEaseOut` — 300 ms, opacity for create and delete; - `LayoutAnimation.Presets.linear` — 500 ms; - `LayoutAnimation.Presets.spring` — 700 ms, a spring with `springDamping: 0.4` for updates. `configureNext` also accepts an end callback; the implementation races it with a timer of the duration plus one frame, so it fires even if native never reports completion. ## The Android flag For years, the documentation told you to enable LayoutAnimation on Android with: - `UIManager.setLayoutAnimationEnabledExperimental(true)` inside a `Platform.OS === 'android'` check. The pinned 0.87 documentation still shows that snippet, but the New Architecture, the only architecture since React Native 0.82, implements LayoutAnimation in the shared C++ renderer. In that UI manager, `setLayoutAnimationEnabledExperimental` is a **no-op** that logs a development warning that it does nothing in the New Architecture. Removing the call is safe; keeping it only adds noise. ## In the social app Liking a post changes its counter from "999" to "1,000" and a "You and 999 others" line appears below. Wrapping the state change with `LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)` makes the action row widen smoothly and the new line fade in, while the heart itself pops with `Animated`. ## Limits and trade-offs - **Global per commit:** everything that changes layout in that commit animates, including unrelated views that happened to re-layout. - **Fire and forget:** you cannot pause, reverse or drive it from a gesture. - **Not for continuous motion:** it animates between two layouts, not along a path. - **Lists:** combining it with list updates can animate rows in unexpected ways; test such screens carefully. When you need per-view control over a layout property, the options are a JS-driven `Animated` animation or, on the experimental Shared Animation Backend, a native-driven one. ## Writing a custom config A custom configuration is a plain object: - `duration: 250`; - `create: {type: 'easeOut', property: 'opacity'}` so new rows fade in; - `update: {type: 'spring', springDamping: 0.7}` so moved views settle with a light spring; - `delete: {type: 'easeIn', property: 'scaleXY'}` so removed views shrink away. The `type` values are `spring`, `linear`, `easeInEaseOut`, `easeIn`, `easeOut` and `keyboard`, and the `property` values for create and delete are `opacity`, `scaleX`, `scaleY` and `scaleXY`. ## How it relates to Animated - `Animated` changes **values** that you bind to styles, frame by frame; `LayoutAnimation` changes nothing itself and animates the **difference between two layouts**. - `Animated` with the native driver cannot animate layout props in a stable app; `LayoutAnimation` exists precisely for layout changes. - The two combine well: a like can pop the heart with `Animated` while `LayoutAnimation` smooths the row's reflow.
- Why must LayoutAnimation.configureNext be called before setState rather than after?It configures the next layout commit. Calling it after `setState` risks the commit it was meant for having been scheduled or applied already, so the change jumps and the configuration applies to some later, unrelated layout. Call it immediately before the state update that changes layout.
- When is LayoutAnimation the wrong tool compared with Animated?When the motion must be interruptible, gesture-driven or limited to one view. LayoutAnimation animates every layout change in one commit and cannot be paused or reversed. A heart pop, a draggable card or a looping pulse belong to `Animated` or a worklet library; LayoutAnimation suits one-off reflows like a row expanding.
saying these in an interview costs you the question
- LayoutAnimation still needs setLayoutAnimationEnabledExperimental(true) on Android in 0.87
- configureNext animates only the view that called it
- LayoutAnimation can be interrupted and reversed like an Animated value
- configureNext should be called after the state change it animates
- LayoutAnimation requires useNativeDriver: true in its config