How to find out FlatList scroll direction

FlatList scroll direction with Reanimated 2

How to find out FlatList scroll direction

FlatList is a performant way to build lists in React Native. In some cases, you need to interact with scroll movement. For example hiding header, footer, or FAB button.

Let's see how we can find out the scroll direction of FlatList. In our example, we are going to use FlatList with Reanimated 2 library because of performance.

import React from 'react';
import {
  SafeAreaView,
  View,
  FlatList,
  StyleSheet,
  Text,
  StatusBar,
} from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedScrollHandler,
  useAnimatedStyle,
  useAnimatedProps,
} from 'react-native-reanimated';
const AnimatFlatList = Animated.createAnimatedComponent(FlatList);

We imported the necessary packages and created Animated FlatList.Then let's see how we find out scroll direction.

useAnimatedScrollHandler is really helpful hooks in Reanimated. In this hook onScroll, onBeginDrag and onEndDrag methods are provided.

We have created two shared values  lastContentOffset and isScrolling. when onScroll the event fired, we need to compare contentOffset value with the previous value. then also we need to know if it's scrolling. otherwise when  FlatList bounces back we will get in the wrong direction.

const App = () => {
  const lastContentOffset = useSharedValue(0);
  const isScrolling = useSharedValue(false);

  const renderItem = ({ item }) => <Item title={item.title} />;
  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (event) => {
      if (lastContentOffset.value > event.contentOffset.y) {
        if (isScrolling.value) {
          console.log('UP');
        }
      } else if (lastContentOffset.value < event.contentOffset.y) {
        if (isScrolling.value) {
          console.log('DOWN');
        }
      }
      lastContentOffset.value = event.contentOffset.y;
    },
    onBeginDrag: (e) => {
      isScrolling.value = true;
    },
    onEndDrag: (e) => {
      isScrolling.value = false;
    },
  });
  return (
    <SafeAreaView style={styles.container}>
      <AnimatFlatList
        data={DATA}
        onScroll={scrollHandler}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
      />
    </SafeAreaView>
  );
};

That's all, you can find Runnable Snack in here