Lottie animations in react native
Tags: react, reactnative, mobile, animations
Published: 2021-06-09 01:00:12

This tutorial is also available as a video, you can check it out At YouTube: 

{% youtube IuTqtPhN-XI %}

Lottie is an easy way of developing Lightweight, scalable animations for websites and applications.
Lottie has been [Introduced in 2017](https://medium.com/airbnb-engineering/introducing-lottie-4ff4a0afac0e) by airbnb. At the time, adding animations to an application was no easy task and ofently resulted in verbose and hard to maintain code, since engineers had to manually recreate the animations in order to use them. The other option was adding a gif or a video to replace the animation, which wasn't as good as programming it, and also made bundle sizes heavy.

> *"After Effects animations in real time, and allows native apps to use animations as easily as they use static assets."* - Airbnb engineering, 2017

Lottie's animations are exported directly from Adobe After Effects in JSON format. That is possible thanks to an AE (After Effects) extension called [Bodymovin](https://exchange.adobe.com/creativecloud.details.12557.bodymovin.html)

Thanks to that, applications can have awesome animations,  without the painstaking overhead of re-writing them.

But enough with introductions,Let's build something with lottie, so you can understand its wonders in pratice.


## What are we building


![a blank heart animation that gets clicked, and is gradually filled with the color red](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/48zjbueagqfpkegrrhpf.gif)


this awesome like interaction is what we will be building today. When it gets clicked, it's gradually colored and filled. If it has already been clicked, we run the animation in reverse, returning the heart to its blank, initial state.


## Pre requisites

In order to succesfully complete this tutorial you are going to need:

- [Node](https://nodejs.org/en/)
- [React Native's CLI](https://reactnative.dev/docs/environment-setup)


## Starting

The first thing we needo to do, is create a react native project, so navigate to your preferred folder and initialize a new react native application. I'm going to name my application "lottieTuto" but you can call yours whatever you like

```bash
npx react-native init lottieTuto
```

Once our application is created, navigate to it and install the following dependencies

- lottie-react-native
- lottie-ios

you can do this using yarn, with the following command:


```
yarn add lottie-ios@3.1.8 lottie-react-native
```

Alternatively, you can use the following command to install them with npm 


```
npm i --save lottie-ios@3.1.8 lottie-react-native
```
## Finding animations

![Lottie files website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hp5zfh3uynl4d7125n7e.png)
[Lottie Files](https://lottiefiles.com/featured) contains an imense catalogue of free animations you can browse in search for the one that fits your app.

We will be using [this one](https://lottiefiles.com/48904-like) today, but feel free to take your time and delight yourself with the awesome animations available at lottie files.


![Downloading lottie JSON](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6qhtty5ramyxgucttoh.gif)


In the selected animation's page, just click in the download button, and choose the lottie json option. 

Inside the application we created earlier, create a folder called assets, and save the downloaded file into it.

![assets folder with a file called like.json inside it](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wh6m5a5x5d8i6gswb7ey.png)
 
**Now we finally have everything we need to start coding our application**

## Updating the code

Inside App.js, replace the default code for the following one


```javascript
//App.js

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

const App = () => {
  return (
    <View style={styles.styles}>
      <Text>Hello Lottie!</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  main: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default App;
```

Now that we have the basic code we are going to work with, is time to import some dependencies:

- LottieView
- Our animation from the assets folder


then proceed to replace the existent 

```javascript
<Text>Hello Lottie!</Text>
```

with

```javascript
//App.js
<LottieView source={like} />
```

after these changes your code should look like this

```javascript
//App.js
import React from 'react';
import {View, StyleSheet} from 'react-native';
import LottieView from 'lottie-react-native';
import like from './assets/like.json';

const App = () => {
  return (
    <View style={styles.styles}>
      <LottieView source={like} />
    </View>
  );
};

const styles = StyleSheet.create({
  main: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default App;
```


> Warning: sometimes when you add LottieView into your code, it breaks your application. If this is happening to you all that you gotta do is reload your app and the error shall disappear


Now you should be seeing the file we downloaded

![Blank Heart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1xaf76d25wozx3hg8wed.png)

But our animation, isn't animated yet.

## Animating our file

We have many ways of animating a lottie file. The one we are going to use today is by using the progress prop.

The progress prop expects a value ranging from 0 (representing the animation's start) to 1 (representing the animation's end).

All that we need to do in order for our lottie file to be animated, is update this value at a steady pace for a specific range of time.

Thankfully for us react native's Animated module handles this behavior for us.


To use it, we are going to need to import 2 things

- useRef - from react
- Animated - from react native


with these 2 imports made, create the following constant

```javascript
const progress = useRef(new Animated.Value(0)).current;
```

> *Why are we using useRef ?*

Because we want our Animated Value to be created once, instead of everytime our component re-renders, and useRef is perfect for this kind of situation.


now we need to create a function that's going to update progress's value

```javascript
//App.js
const handleLikeAnimation = () => {
    Animated.timing(progress, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true,
    }).start();
  };
```

what are we doing in this function exactly ?

Well, Animated.timing is the function responsible for updating our value from one value to another at a steady pace for a specific range of time.

It accepts two parameters, the first one is the value being updated. Note that this value must be an **Animated.Value**.

The second parameter is an object that must contain these 3 properties.

- toValue - your final value
- duration - the time required to your value to go from the original value to the final one
- useNativeDriver - [Check the docs](https://reactnative.dev/docs/animations#using-the-native-driver) (This one is a little too complex to be explained in one line 😅

We also need to wrap our LottieView inside a TouchableOpacity, since LottieView isn't clickable itself we need a way to call our handleLikeAnimationFunction

after all these changes, this is how our code looks like


```javascript

import React, {useRef} from 'react';
import {View, StyleSheet, Animated, TouchableOpacity} from 'react-native';
import LottieView from 'lottie-react-native';
import like from './assets/like.json';

const App = () => {
  const progress = useRef(new Animated.Value(0)).current;

  const handleLikeAnimation = () => {
    Animated.timing(progress, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true,
    }).start();
  };

  return (
    <View style={styles.main}>
      <TouchableOpacity onPress={handleLikeAnimation} style={styles.opacity}>
        <LottieView progress={progress} source={like} />
      </TouchableOpacity>
    </View>
  );
};

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

export default App;
```

Once we have done that, when we click our Heart, its animation is triggered!

But theres one last thing missing. Once our animation has been triggered, pressing it again won't do anything

Thankfully, that's an easy fix.

That happens because our initial value is 0, and we are always updating it to be 1, even when it's already 1. So in order to fix this, you just have to check if your animation state is at the finish (1) or at the begining 0. 

This is our application's final code


```javascript
import React, {useRef, useState} from 'react';
import {View, StyleSheet, Animated, TouchableOpacity} from 'react-native';
import LottieView from 'lottie-react-native';
import like from './assets/like.json';

const App = () => {
  const progress = useRef(new Animated.Value(0)).current;
  const [hasLiked, setHasLiked] = useState(false);

  const handleLikeAnimation = () => {
    const newValue = hasLiked ? 0 : 1;

    Animated.timing(progress, {
      toValue: newValue,
      duration: 1000,
      useNativeDriver: true,
    }).start();

    setHasLiked(!hasLiked);
  };

  return (
    <View style={styles.main}>
      <TouchableOpacity onPress={handleLikeAnimation} style={styles.opacity}>
        <LottieView progress={progress} source={like} />
      </TouchableOpacity>
    </View>
  );
};

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

export default App;
```


That's it for today folks. I really hope this post has been helpful for you

If you enjoyed this tutorial, please consider subscribing to my youtube's channel: https://www.youtube.com/channel/UC4HtvYKMv7uvcO3CwzCCSDg/featured

and following me on twitter: https://twitter.com/MobileMagic5