How to create Animated FlatList in React-Native
Tags: reactnative, expo, tutorial, typescript
Published: 2021-09-03 14:53:05

Hey guys, I am Mazahir. 
Today we are gonna learn how to use **Animated API** with **FlatList** to create
beautiful animations.

## Requirements
* Latest version of **expo** and **react-native** installed
* Basic of expo with **typescript**
* Nothing else, Let's get started

## Preview
Before we get our hands dirty, let's see what are we trying to make.
![react-natve animated flatlist](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2e4w5dwjubbp4gonz6mi.gif)

Your project will end up looking like this.


## Initialization
* Create a new expo project

  `expo init -t expo-template-blank-typescript`


* After Creating a new project, We need some data to display. I am using faker to create  fake data but you can use an **API** or **Hard Coded** data as well.

### How to create fake data using faker

 * `npm i faker`
 *  Paste this code snippet.
   ```
// Inside App.tsx
const fake : string[] = new Array(20).fill('test');
const data: data[] = fake.map(() => ({
    name: faker.name.findName(),
    job_title: faker.name.jobTitle(),
    email: faker.internet.email(),
    key: faker.random.alphaNumeric(10),
    avatar: faker.image.avatar(),
  }));
  ```
 * I am using **react-native-paper** for styling. Its not  necessary for you to install, but I highly recommend it.

`npm i react-native-paper`

## FlatList & Animations

* To create beautiful animations like I said, We first need a FlatList. Create a folder named components and add a file named list.tsx.


* Add the required import statements.

``` 
// inside components/list.tsx
import * as React from "react";
import { Text, View, StyleSheet, Animated, Dimensions } from "react-native";
import { Avatar, Surface } from "react-native-paper";

const { height } = Dimensions.get("screen");
```
_I am getting the height of the screen as well, which will be useful later_

* Now, we will create a basic function and a normal flatlist

```
interface Data {
  name: string;
  email: string;
  job_title: string;
  key: string;
  avatar: string;
}

export default function List({ data }: { data: Data[] }) {
  return (
    <View style={styles.container}>
      <Animated.FlatList
        data={data}
        keyExtractor={(item) => item.key}
        renderItem={({ item, index }) => {
          
          return (
            <Animated.View>
              <Surface style={styles.surface}>
                <View style={{ flex: 0.3, justifyContent: "center" }}>
                  <Avatar.Image size={42} source={{ uri: item.avatar }} />
                </View>
                <View
                  style={{
                    flex: 0.7,
                    flexDirection: "column",
                    justifyContent: "center",
                  }}
                >
                  <Text style={{ fontSize: 22, fontWeight: "bold" }}>
                    {item.name}
                  </Text>
                  <Text style={{ fontSize: 14 }}>{item.job_title}</Text>
                </View>
              </Surface>
            </Animated.View>
          );
        }}
      />
    </View>
  );
}
 


const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
  },
  surface: {
    height: height * 0.1,
    marginTop: 15,
    padding: 8,
    marginHorizontal: 10,
    borderRadius: 8,
    flexDirection: "row",
  },
});
```
_Even if i add Animated.FlatList or Animated.View, it will work as normal View and FlatList._

### Animations

* Inside list.tsx, Create a ref for an animated value
`const scrollY = React.useRef(new Animated.Value(0)).current;`
_This will store the scroll offset of the Flatlist._

* To update the *scrollY*. 
```
onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: scrollY } } }],
          { useNativeDriver: true }
        )}
```
_Here we assign y offset of the list to our ref, useNativeDriver is true, that's something we don't need to worry about right now_

* if you save the changes, everything should work fine but there are no animations.

 1. to animate list we need 2 things *input range* and *output range*
 2. You can think of input range and output range as key frames if u know what that means.
 3. To define it input range is a set of values at which you want to animate or change a value.
 4. Output range is set of values that react or change based on the input range.
 _It's okay if u did not understand it._

* Enough theory let's get some animation on the screen.
 Inside the renderItem function we will add
```
const inputRange = [
   -1,
   0,
   (height * 0.1 + 15) * index,
   (height * 0.1 + 15) * (index + 3),
 ];
```
height * 0.1 because that the height of the item or the view according to the style, we add 15 because of the margin.

when the content offset is at -1 or 0 we don't want any changes to the view or item, but we want to start the animation as soon as the item touches the top and the animation to end when the 3rd element( 3rd element from the current item) touches the top.

* Now to animate the opacity
```
const opacity = scrollY.interpolate({
   inputRange,
   outputRange: [1, 1, 1, 0],
 });
```
we store the animated value in const opacity. scrollY.interpolate it takes 1 argument an object with 2 array the input range and the outputrange.

* We also need to translateX or to move the view on the x-axis. so we create interpolated value.
```
const Offset = scrollY.interpolate({
   inputRange,
   outputRange: [0, 0, 0, 500],
 });
```

* That's it, We have all the values we need. The only thing left to do is just wire them up.
```
<Animated.View
        style={{
                transform: [{ translateX: Offset }],
                opacity: opacity,
              }}
            >
```
if save the changes, You should have working animations. if you got an error or the code does not work then you can check it with the my completed code [here](https://github.com/Mazahir26/react-native-animated-flatlist)

* You can play around with the input range and output range
and get different results

## Conclusion
Animation in react native is pretty simple if you know what you are doing.

You can find the completed code  [here](https://github.com/Mazahir26/react-native-animated-flatlist)

I hope you enjoyed and learned something out of this.
Any suggestions or feedback would be awesome. :)

Thank you.