How to Implement Lottie Animations in React Native / React

You have a beautiful Lottie animation. It is optimized, under 45KB, and ready to go. Now you need to get it into your React or React Native app. This is where many developers get stuck. The implementation seems straightforward, but there are nuances that can trip you up.

I have implemented Lottie animations in dozens of React and React Native projects. I have made the mistakes. I have debugged the issues. I have learned the best practices. This guide is the result of that experience.

We will cover both React (web) and React Native (mobile). The approaches are similar but have important differences. By the end, you will know exactly how to add Lottie animations to your projects.

Why Lottie in React / React Native?

Before we dive into the code, let us briefly recap why Lottie is such a great fit for React and React Native projects.

React and React Native are component-based. Lottie animations are component-friendly. You can wrap them in a component and reuse them anywhere. They are declarative, just like React itself.

Lottie also solves the performance problems that plague GIFs and videos in React Native. GIFs are heavy and cause jank. Videos are complex to manage. Lottie is lightweight and smooth.

Implementing in React Native

React Native has excellent Lottie support through the lottie-react-native library. Let us walk through the setup and usage.

Installation

The installation process differs between iOS and Android. Here is the full setup.

Step 1: Install the library

npm install lottie-react-native
# or
yarn add lottie-react-native

Step 2: iOS Setup

For iOS, you need to install the native Lottie iOS framework. If you are using CocoaPods, add this to your ios/Podfile:

pod 'lottie-ios'

Then run:

cd ios && pod install

If you are using the new architecture (Fabric), the setup is different. The library version 6.x supports the new architecture.

Step 3: Android Setup

For Android, you need to add the Lottie Android library to your android/app/build.gradle:

dependencies {
    implementation 'com.airbnb.android:lottie:6.0.0'
}

You also need to enable the new architecture if you are using it. The library version 6.x supports both old and new architectures.

Step 4: Metro Configuration

Add the following to your metro.config.js to handle Lottie assets:

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: true,
      },
    }),
  },
  resolver: {
    assetExts: ['lottie'],
  },
};

Basic Usage

Once installed, using Lottie in React Native is straightforward.

import React from 'react';
import { View, StyleSheet } from 'react-native';
import LottieView from 'lottie-react-native';

const MyAnimation = () => {
  return (
    <View style={styles.container}>
      <LottieView
        source={require('./assets/animations/animation.json')}
        autoPlay
        loop
        style={styles.animation}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  animation: {
    width: 200,
    height: 200,
  },
});

export default MyAnimation;

That is it. A few lines of code and your animation is running.

Controlling the Animation

The real power of Lottie comes from programmatic control. You can play, pause, reset, and control the speed.

import React, { useRef } from 'react';
import { View, Button, StyleSheet } from 'react-native';
import LottieView from 'lottie-react-native';

const ControlledAnimation = () => {
  const animationRef = useRef(null);

  const handlePlay = () => {
    animationRef.current?.play();
  };

  const handlePause = () => {
    animationRef.current?.pause();
  };

  const handleReset = () => {
    animationRef.current?.reset();
  };

  return (
    <View style={styles.container}>
      <LottieView
        ref={animationRef}
        source={require('./assets/animations/animation.json')}
        style={styles.animation}
      />
      <View style={styles.buttonContainer}>
        <Button title="Play" onPress={handlePlay} />
        <Button title="Pause" onPress={handlePause} />
        <Button title="Reset" onPress={handleReset} />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  animation: {
    width: 200,
    height: 200,
  },
  buttonContainer: {
    flexDirection: 'row',
    marginTop: 20,
    gap: 10,
  },
});

export default ControlledAnimation;

Controlling Speed

You can also control the playback speed.

const handleSlowMotion = () => {
  animationRef.current?.setProgress(0.5); // 0.5x speed
};

const handleNormalSpeed = () => {
  animationRef.current?.setProgress(1);
};

const handleFastSpeed = () => {
  animationRef.current?.setProgress(2);
};

Playing Specific Segments

You can play a specific segment of the animation using play with start and end frame parameters.

const handlePlaySegment = () => {
  animationRef.current?.play(0, 30); // Play frames 0-30
};

Handling Animation Events

Lottie also provides events you can listen to.

const MyAnimation = () => {
  const handleAnimationFinish = () => {
    console.log('Animation finished!');
  };

  const handleAnimationLoop = () => {
    console.log('Animation looped!');
  };

  return (
    <LottieView
      source={require('./assets/animations/animation.json')}
      autoPlay
      loop
      onAnimationFinish={handleAnimationFinish}
      onLoop={handleAnimationLoop}
      style={styles.animation}
    />
  );
};

Implementing in React (Web)

For web applications, the implementation is similar but uses the lottie-web library.

Installation

npm install lottie-web
# or
yarn add lottie-web

Alternatively, you can use the react-lottie wrapper library for a more React-friendly API:

npm install react-lottie
# or
yarn add react-lottie

Basic Usage with react-lottie

import React from 'react';
import Lottie from 'react-lottie';
import animationData from './assets/animations/animation.json';

const MyAnimation = () => {
  const defaultOptions = {
    loop: true,
    autoplay: true,
    animationData: animationData,
    rendererSettings: {
      preserveAspectRatio: 'xMidYMid slice',
    },
  };

  return <Lottie options={defaultOptions} height={200} width={200} />;
};

export default MyAnimation;

Controlling the Animation

With react-lottie, you can control the animation using the isStopped, isPaused, and speed props.

import React, { useState } from 'react';
import Lottie from 'react-lottie';
import animationData from './assets/animations/animation.json';

const ControlledAnimation = () => {
  const [isStopped, setIsStopped] = useState(false);
  const [isPaused, setIsPaused] = useState(false);
  const [speed, setSpeed] = useState(1);

  const defaultOptions = {
    loop: true,
    autoplay: true,
    animationData: animationData,
    rendererSettings: {
      preserveAspectRatio: 'xMidYMid slice',
    },
  };

  return (
    <div>
      <Lottie
        options={defaultOptions}
        height={200}
        width={200}
        isStopped={isStopped}
        isPaused={isPaused}
        speed={speed}
      />
      <button onClick={() => setIsStopped(!isStopped)}>Toggle Stop</button>
      <button onClick={() => setIsPaused(!isPaused)}>Toggle Pause</button>
      <button onClick={() => setSpeed(0.5)}>Slow</button>
      <button onClick={() => setSpeed(1)}>Normal</button>
      <button onClick={() => setSpeed(2)}>Fast</button>
    </div>
  );
};

export default ControlledAnimation;

Using lottie-web Directly

If you prefer more control, you can use lottie-web directly with React hooks.

import React, { useEffect, useRef } from 'react';
import lottie from 'lottie-web';
import animationData from './assets/animations/animation.json';

const MyAnimation = () => {
  const containerRef = useRef(null);

  useEffect(() => {
    const instance = lottie.loadAnimation({
      container: containerRef.current,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData: animationData,
    });

    return () => {
      instance.destroy();
    };
  }, []);

  return <div ref={containerRef} style={{ width: 200, height: 200 }} />;
};

export default MyAnimation;

Optimizing Lottie in React Native

Performance is critical in mobile apps. Here are my tips for optimizing Lottie in React Native.

1. Use dotLottie Format

The dotLottie (.lottie) format is compressed and loads faster. Use it instead of raw JSON when possible.

import { DotLottiePlayer } from '@dotlottie/react-player';

// Instead of LottieView, use DotLottiePlayer for better performance

2. Enable Hardware Acceleration

Set the renderer to 'software' on Android for better performance on older devices. For newer devices, the default is fine.

<LottieView
  source={require('./animation.lottie')}
  renderer="software" // For Android
  autoPlay
  loop
/>

3. Freeze Offscreen Animations

Stop rendering animations when they are not visible. Use the freezeOnOffscreen prop.

<LottieView
  source={require('./animation.lottie')}
  freezeOnOffscreen
  autoPlay
  loop
/>

4. Use WebGL Renderer for Complex Animations

For complex animations, the WebGL renderer performs better than the default SVG renderer.

<LottieView
  source={require('./animation.lottie')}
  renderer="webgl"
  autoPlay
  loop
/>

5. Preload Animations

Preload animations to avoid jank when they first appear.

import { LottieView } from 'lottie-react-native';

// Preload the animation before using it
const animation = require('./assets/animations/animation.lottie');

// Then use it later
<LottieView source={animation} autoPlay />

Common Issues and Solutions

Here are the issues I have encountered most frequently and how to fix them.

Issue 1: Animation Not Rendering on iOS

This is usually a pod installation issue. Ensure you have run pod install after installing the library. Also, make sure your animation file is in the correct location and properly required.

Solution: Clean and rebuild.

cd ios && pod install
cd .. && npx react-native run-ios

Issue 2: Large File Size on Android

Use the dotLottie format instead of JSON. dotLottie files are compressed.

Solution: Convert your JSON to dotLottie using the LottieFiles converter.

Issue 3: Animation Causing Jank

Reduce the complexity of the animation. Use fewer layers and shapes. Or enable WebGL rendering.

Solution: Use renderer="webgl" for complex animations.

Issue 4: Animation Not Looping Properly

Check your animation settings. Use the loop prop and set it to true. Or use setLoop with a reference.

const animationRef = useRef(null);

// Later
animationRef.current?.setLoop(true);

Best Practices

After implementing Lottie in many projects, here are my best practices.

1. Centralize Your Animations

Create a centralized animation registry. This makes it easy to manage and update animations across your app.

// animations/index.js
import animation1 from './animations/animation1.lottie';
import animation2 from './animations/animation2.lottie';
import animation3 from './animations/animation3.lottie';

export const ANIMATIONS = {
  loading: animation1,
  success: animation2,
  error: animation3,
};

// Use it anywhere
import { ANIMATIONS } from './animations';

<LottieView source={ANIMATIONS.loading} autoPlay />

2. Use Theme-Aware Animations

Store theme colors as motion tokens in the dotLottie file. This allows the animation to adapt to light and dark modes automatically.

4. Handle Different Screen Sizes

Use responsive dimensions for your animations. Do not hardcode pixel values.

import { Dimensions } from 'react-native';
const { width, height } = Dimensions.get('window');

<LottieView
  source={require('./animation.lottie')}
  style={{
    width: width * 0.5,
    height: height * 0.3,
  }}
  autoPlay
/>

5. Use Reanimated for Performance

For complex animations that need to respond to gestures or scroll events, use React Native Reanimated with Lottie.

import Animated from 'react-native-reanimated';
import LottieView from 'lottie-react-native';

const AnimatedLottie = Animated.createAnimatedComponent(LottieView);

Conclusion

Implementing Lottie in React and React Native is straightforward. The libraries are mature and well-documented. The API is consistent across platforms. With the optimizations I have shared, your animations will be smooth and performant.

The key is to start simple. Get the animation working. Then add control, interactivity, and optimizations. Use dotLottie for smaller files. Freeze offscreen animations. Use the right renderer for your use case.

Lottie transforms how you add motion to your React and React Native applications. It is a tool every developer should have in their toolkit.

Frequently Asked Questions

Can I use Lottie in React Native without native dependencies?

No. Lottie React Native requires native dependencies. The library uses the native Lottie libraries for iOS and Android.

What is the difference between lottie-react-native and lottie-web?

lottie-react-native is for React Native (mobile apps). It uses native rendering. lottie-web is for React (web applications). It renders in the browser.

How do I update the animation color dynamically in React Native?

You can use dotLottie with motion tokens. Define the color as a token in the dotLottie file. Then update the token value in your code.

Can I use Lottie with Expo?

Yes. Use the expo-lottie library for Expo projects. It provides a wrapper around lottie-react-native.

What is the best way to handle Lottie animations in a React Native list?

Use flatlist optimization techniques. Use the freezeOnOffscreen prop to stop rendering offscreen animations. Use smaller, simpler animations in lists.