Skip to main content
LayoutAnimation automatically animates views to their new positions when the next layout happens. A common way to use this API is to call it before calling setState.
On Android, you need to enable LayoutAnimation by setting the following flag in your UIManager:
import {UIManager, Platform} from 'react-native';

if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
  }
}

Methods

configureNext()

static configureNext(
  config: LayoutAnimationConfig,
  onAnimationDidEnd?: () => void,
  onAnimationDidFail?: () => void
)
Schedules an animation to happen on the next layout.
config
object
required
Specifies animation properties:
duration
number
required
Duration of the animation in milliseconds
create
object
Configuration for animating in new views
type
string
Animation type: spring, linear, easeInEaseOut, easeIn, easeOut, or keyboard
property
string
Property to animate: opacity, scaleX, scaleY, or scaleXY
springDamping
number
Spring damping coefficient (only for spring type)
update
object
Configuration for animating views that have been updated
type
string
Animation type: spring, linear, easeInEaseOut, easeIn, easeOut, or keyboard
springDamping
number
Spring damping coefficient (only for spring type)
delete
object
Configuration for animating out removed views
type
string
Animation type: spring, linear, easeInEaseOut, easeIn, easeOut, or keyboard
property
string
Property to animate: opacity, scaleX, scaleY, or scaleXY
onAnimationDidEnd
function
Callback called when the animation completes. Guaranteed to be called in Fabric renderer.
onAnimationDidFail
function
Callback called on error. Only called in Fabric renderer if configuration parsing fails.

create()

static create(
  duration: number,
  type?: string,
  property?: string
): LayoutAnimationConfig
Helper for creating a config for configureNext().
duration
number
required
Duration of the animation in milliseconds
type
string
Animation type: spring, linear, easeInEaseOut, easeIn, easeOut, or keyboard
property
string
Property to animate: opacity, scaleX, scaleY, or scaleXY

Preset Methods

easeInEaseOut()

static easeInEaseOut(onAnimationDidEnd?: () => void)
Uses the easeInEaseOut preset (300ms duration, opacity property).

linear()

static linear(onAnimationDidEnd?: () => void)
Uses the linear preset (500ms duration, opacity property).

spring()

static spring(onAnimationDidEnd?: () => void)
Uses the spring preset (700ms duration, spring damping 0.4).

Properties

Types

Available animation types:
LayoutAnimation.Types = {
  spring: 'spring',
  linear: 'linear',
  easeInEaseOut: 'easeInEaseOut',
  easeIn: 'easeIn',
  easeOut: 'easeOut',
  keyboard: 'keyboard',
}

Properties

Available animation properties:
LayoutAnimation.Properties = {
  opacity: 'opacity',
  scaleX: 'scaleX',
  scaleY: 'scaleY',
  scaleXY: 'scaleXY',
}

Presets

Pre-configured animation presets:
LayoutAnimation.Presets = {
  easeInEaseOut: {...},
  linear: {...},
  spring: {...},
}

Examples

Basic Usage with setState

import React, {useState} from 'react';
import {View, Button, LayoutAnimation, StyleSheet} from 'react-native';

function BasicExample() {
  const [expanded, setExpanded] = useState(false);

  const toggleBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    setExpanded(!expanded);
  };

  return (
    <View style={styles.container}>
      <Button title="Toggle" onPress={toggleBox} />
      <View
        style={[
          styles.box,
          {width: expanded ? 200 : 100, height: expanded ? 200 : 100}
        ]}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  box: {
    backgroundColor: 'blue',
    marginTop: 20,
  },
});

Custom Configuration

import React, {useState} from 'react';
import {View, Button, LayoutAnimation} from 'react-native';

function CustomAnimation() {
  const [width, setWidth] = useState(100);

  const animate = () => {
    LayoutAnimation.configureNext({
      duration: 700,
      create: {
        type: LayoutAnimation.Types.spring,
        property: LayoutAnimation.Properties.scaleXY,
      },
      update: {
        type: LayoutAnimation.Types.spring,
        springDamping: 0.4,
      },
      delete: {
        type: LayoutAnimation.Types.linear,
        property: LayoutAnimation.Properties.opacity,
      },
    });
    setWidth(width === 100 ? 200 : 100);
  };

  return (
    <View>
      <Button title="Animate" onPress={animate} />
      <View style={{width, height: 100, backgroundColor: 'blue'}} />
    </View>
  );
}

With Callbacks

import React, {useState} from 'react';
import {View, Button, LayoutAnimation, Alert} from 'react-native';

function CallbackExample() {
  const [size, setSize] = useState(100);

  const animateWithCallback = () => {
    LayoutAnimation.configureNext(
      LayoutAnimation.Presets.spring,
      () => {
        Alert.alert('Animation Complete!');
      },
      () => {
        Alert.alert('Animation Failed!');
      }
    );
    setSize(size === 100 ? 200 : 100);
  };

  return (
    <View>
      <Button title="Animate" onPress={animateWithCallback} />
      <View style={{width: size, height: size, backgroundColor: 'blue'}} />
    </View>
  );
}

Using create() Helper

import React, {useState} from 'react';
import {View, Button, LayoutAnimation} from 'react-native';

function CreateHelper() {
  const [height, setHeight] = useState(100);

  const animate = () => {
    const customAnimation = LayoutAnimation.create(
      500,
      LayoutAnimation.Types.linear,
      LayoutAnimation.Properties.opacity
    );
    LayoutAnimation.configureNext(customAnimation);
    setHeight(height === 100 ? 200 : 100);
  };

  return (
    <View>
      <Button title="Animate" onPress={animate} />
      <View style={{width: 100, height, backgroundColor: 'blue'}} />
    </View>
  );
}

List Item Addition/Removal

import React, {useState} from 'react';
import {View, Button, Text, LayoutAnimation, StyleSheet} from 'react-native';

function ListAnimation() {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);

  const addItem = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    setItems([...items, `Item ${items.length + 1}`]);
  };

  const removeItem = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    setItems(items.slice(0, -1));
  };

  return (
    <View style={styles.container}>
      <View style={styles.buttons}>
        <Button title="Add" onPress={addItem} />
        <Button title="Remove" onPress={removeItem} />
      </View>
      {items.map((item, index) => (
        <View key={index} style={styles.item}>
          <Text>{item}</Text>
        </View>
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  buttons: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginBottom: 20,
  },
  item: {
    padding: 15,
    backgroundColor: '#e0e0e0',
    marginVertical: 5,
  },
});

Notes

  • Call LayoutAnimation.configureNext() before setState() or other state updates
  • On Android, LayoutAnimation must be explicitly enabled via UIManager
  • Fabric renderer provides more reliable callback support
  • Works with layout property changes (width, height, position)
  • Does not work with transform properties
  • Can impact performance with complex layouts or many simultaneous animations

Build docs developers (and LLMs) love