Integrating Lottie Animations in React Native
AI generated
RN
native
React Native · Lottie · Animation
Integrating Lottie Animations
After Effects quality without video or GIF

Lottie brings animations designers build in After Effects into the app as a compact JSON file and plays them back natively on iOS and Android, without a video file and without hand-written animation code. This article covers the JSON pipeline, programmatic control through play, pause, and dynamic colors, and where Lottie's limits are compared to hand-coded Reanimated animations.

12 min read lottie-react-native Play/pause control Dynamic colors

1. What is Lottie, and how does the JSON pipeline work?

Lottie is a format and rendering library built by Airbnb that exports animations from Adobe After Effects as a JSON file and plays them back natively across platforms. The export runs through the Bodymovin plugin, which translates layers, shapes, paths, and keyframes from After Effects into a declarative JSON description that contains no raster images at all, only pure vector data.

On React Native, lottie-react-native handles parsing and rendering that JSON file by wiring in the native Lottie libraries for iOS and Android under the hood. Playback itself therefore happens natively, comparable to a vector graphic re-interpolated on every frame, not as a played-back video or animated GIF, which results in noticeably smaller file sizes and crisp rendering at any screen size.

2. Setup: installation and a first LottieView

After installing lottie-react-native and doing the required native linking, an animation can be wired up either as a local JSON file through require() or as a remote URL. For production apps, the local variant is usually preferable, since it carries no load time and no dependency on network availability.

The LottieView component handles the entire playback logic: size, looping, and autoplay can be controlled directly through props, while finer control, say deliberately starting after a user event, happens through a ref and imperative methods.


import LottieView from 'lottie-react-native';

function SuccessAnimation() {
  return (
    <LottieView
      source={require('./assets/success-check.json')}
      autoPlay
      loop={false}
      style={{ width: 160, height: 160 }}
    />
  );
}

3. Programmatic control: play, pause, and speed

For use cases where an animation should deliberately start or pause at a specific moment, say after a successful form submission, a ref gets attached to the LottieView. Through it, play(), pause(), and reset() can be called imperatively, optionally with a start and end frame to play only a segment of the animation.

Playback speed can be adjusted through the speed prop, which in practice is useful for reusing the same animation file across different contexts, say a faster version for impatient repeat users and a slower one for the first onboarding moment.


function SubmitButton() {
  const animationRef = useRef<LottieView>(null);
  const [submitting, setSubmitting] = useState(false);

  async function handleSubmit() {
    setSubmitting(true);
    await submitForm();
    animationRef.current?.play(0, 60);
  }

  return (
    <LottieView
      ref={animationRef}
      source={require('./assets/success-check.json')}
      loop={false}
      autoPlay={false}
      onAnimationFinish={() => setSubmitting(false)}
    />
  );
}

4. Dynamic colors without editing the JSON file

A common requirement is adapting a Lottie animation delivered by designers to the current brand color or a dark theme, without maintaining a separate JSON file for every variant. Through the colorFilters prop, individual named layers of the animation can be recolored at runtime, provided the layers were given descriptive names in After Effects.

For more complex cases, lottie-react-native also offers a dynamic properties API that lets you override not just colors but also position, size, or opacity of individual layers at runtime, which enables theming or personalized content within the same animation file.


<LottieView
  source={require('./assets/onboarding-illustration.json')}
  autoPlay
  loop
  colorFilters={[
    { keypath: 'Primary Shape', color: theme.colors.brandPrimary },
    { keypath: 'Accent Shape', color: theme.colors.brandAccent },
  ]}
/>

5. Interactivity: tying progress to scroll or a gesture

The progress prop lets you set an animation's playback progress directly instead of playing it automatically. That allows tying animations to user interactions, say a pull-to-refresh indicator whose progress is set proportionally to the pull distance, or a progress display that exactly matches the scroll position of an onboarding screen.

The important caveat is that every update to progress runs through the JS thread, not through a worklet on the UI thread the way Reanimated works. With very frequent updates, say on every pixel of a scroll gesture, that can cause noticeable lag, which is why throttling the update frequency makes sense in such cases.


const [progress, setProgress] = useState(0);

const scrollHandler = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
  const ratio = event.nativeEvent.contentOffset.y / MAX_SCROLL;
  setProgress(Math.min(Math.max(ratio, 0), 1));
};

<LottieView
  source={require('./assets/progress-indicator.json')}
  progress={progress}
/>

6. Performance characteristics and common bottlenecks

Lottie renders natively and is fast enough for most everyday animations without developers having to worry about the details. With very complex animations that have many layers, masks, or shapes computed through expressions in After Effects, playback can still generate noticeable CPU load on older devices, since every layer has to be re-interpolated on every frame.

In practice, it helps to simplify animations before export in After Effects: merging shapes, removing unnecessary layers, and replacing expressions with fixed keyframes where possible. The newer dotLottie format also bundles several animations and assets into one compressed file, reducing both bundle size and load time compared to individual JSON files.

7. Limits compared to hand-coded Reanimated animations

Lottie excels at fixed, choreographed, designer-crafted sequences such as success checkmarks, loading animations, or onboarding illustrations, where the motion is predetermined. Once an animation needs to react dynamically to physical input, say a card that follows a finger movement in real time and settles naturally, Lottie hits its limits, because playback stays bound to a pre-recorded timeline.

Reanimated and Skia, by contrast, allow fully code-driven, worklet-based animations that can react to any arbitrary input value in real time, without being tied to a fixed keyframe sequence. The pragmatic rule of thumb: designer-authored, fixed sequences belong to Lottie, physically reactive or data-driven interactions belong to Reanimated or Skia.

8. The asset pipeline in practice: export pitfalls

Not every After Effects feature is supported by Lottie renderers. Certain mask and matte types, some expressions, and a few text layer effects either get ignored by the Bodymovin export or lead to visible differences between the After Effects preview and the actual rendering in the app. Testing the exported file in the LottieFiles preview before integration saves a lot of time here.

When working with a design team, it pays to agree early on a list of supported features and deliberately avoid complex effects Lottie cannot represent, rather than discovering them as a bug only after integrating them into the app.

9. Practical example: a success checkmark after form submission

A complete example combines several of the building blocks shown earlier: the animation only starts after a successful server request, plays once, and triggers navigation to the next screen through onAnimationFinish, without the user having to tap forward manually.

This pattern, animation as confirmation of a completed action rather than pure decoration, is one of the most common and, at the same time, most user-friendly uses of Lottie in production apps.


function SuccessScreen({ onDone }: { onDone: () => void }) {
  return (
    <LottieView
      source={require('./assets/success-check.json')}
      autoPlay
      loop={false}
      speed={1.2}
      onAnimationFinish={onDone}
      style={{ width: 200, height: 200, alignSelf: 'center' }}
    />
  );
}
Use case Recommendation Why Alternative
Success checkmark after a form Lottie Fully designed sequence, no custom code needed Reanimated for very simple cases
Physically reactive gesture Reanimated Real-time worklet control required No sensible Lottie alternative
Onboarding illustration Lottie Designer workflow through After Effects Static image on a tight budget
Data-driven chart Skia or Reanimated Lottie cannot change its structure dynamically No sensible Lottie alternative
Pull-to-refresh indicator Lottie with progress control Pre-built motion tied to scroll Reanimated for full control
Loading indicator with brand color Lottie with colorFilters One file usable across multiple themes Custom Reanimated solution

Mironsoft

React Native app development and Magento integration

A mobile app for the Magento shop that actually runs smoothly?

We build React Native apps cleanly connected to the Magento REST or GraphQL API, from the first line of code to publishing on the App Store and Google Play.

App Concept

Plan the architecture and feature scope of a Magento-connected app together.

Magento API Integration

Cleanly connect product catalog, cart, and checkout to the shop API.

Store Publishing

Guide the App Store and Google Play release process without pitfalls.

10. Summary

Lottie in React Native

Core idea

Lottie plays animations designers build in After Effects natively from compact JSON, without video or GIF.

Control

A ref lets you call play, pause, reset, speed, and progress imperatively.

Dynamic colors

colorFilters recolors named layers at runtime without editing the JSON file.

Limit

Fixed choreographed sequences belong to Lottie, physically reactive interactions belong to Reanimated.

11. FAQ: Lottie in React Native

1What is the difference between Lottie and an animated GIF?
A GIF is a sequence of raster images with limited color depth and a fixed resolution, while Lottie contains vector data that renders crisply at any screen size and produces noticeably smaller files.
2How do I export a Lottie animation from After Effects?
Through the free Bodymovin plugin, which translates the layers, shapes, and keyframes of an After Effects composition into a JSON file that can then be loaded directly into lottie-react-native.
3How do I start a Lottie animation deliberately on a button press?
Through a ref on the LottieView and an imperative call to play(), optionally with a start and end frame, while autoPlay stays set to false.
4Can I change the colors of a Lottie animation at runtime?
Yes, through the colorFilters prop, individual named layers can be recolored at runtime, provided the layers were given clear names in the design tool.
5Why does my Lottie animation stutter on older devices?
Usually because of too many layers, complex masks, or expressions from After Effects that need to be recalculated on every frame. Simplifying the animation before export usually helps significantly.
6Can I tie the progress of a Lottie animation to a scroll gesture?
Yes, through the progress prop, which can be set manually. With very frequent updates, throttling is recommended, since every update runs through the JS thread rather than directly on the UI thread like Reanimated.
7What is dotLottie, and when is it worth using?
dotLottie is a compressed container format that bundles several animations and assets into one file, reducing bundle size and load time compared to individual JSON files, especially for apps with many Lottie animations.
8Should I use Lottie or Reanimated for a swipe gesture with a spring-back effect?
Reanimated, because such a gesture needs to react to finger movement in real time. Lottie is bound to a pre-recorded timeline and is not suited for physically reactive interactions.
9Does Lottie support every After Effects feature?
No, certain mask types, some expressions, and a few text layer effects are not or only partially supported by Lottie renderers. Testing in the LottieFiles preview before integration catches such discrepancies early.
10Can I react to the end of an animation with onAnimationFinish?
Yes, the onAnimationFinish callback fires once playback completes and is well suited for automatically navigating afterward or resetting a piece of state.