DEV Community

Cover image for React Native Smooth Scroll: A Lightweight and Customizable Component
babar bilal
babar bilal

Posted on • Edited on

React Native Smooth Scroll: A Lightweight and Customizable Component

Introduction

Infinite scrolling is an essential feature for modern mobile applications, allowing users to seamlessly browse long lists of data without manually loading more items. To simplify this functionality, I’ve built react-native-smooth-scroll, a lightweight and customizable infinite scroll component for React Native that supports pagination, pull-to-refresh, and error handling.

Features

Infinite Scroll: Automatically loads more data as the user scrolls.

Pagination: Supports paginated data fetching.

Pull-to-Refresh: Allows refreshing the list with a pull gesture.

Error Handling: Displays an error message if data fetching fails.

Customizable: Customize the loader, error, and empty list components.

Installation

Install the library using npm or yarn:

npm install react-native-smooth-scroll
Enter fullscreen mode Exit fullscreen mode

OR

yarn add react-native-smooth-scroll
Enter fullscreen mode Exit fullscreen mode

Usage

Basic Example

import React, { useState, useEffect } from 'react';
import { SafeAreaView, StyleSheet, Text, View } from 'react-native';
import InfiniteScroll from 'react-native-smooth-scroll';

const App = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);
  const [isRefreshing, setIsRefreshing] = useState(false);
  const [error, setError] = useState(null);

  const fetchData = async (pageNumber) => {
    try {
      const response = await fetch(
        `https://jsonplaceholder.typicode.com/posts?_limit=10&_page=${pageNumber}`
      );
      if (!response.ok) throw new Error('Failed to fetch data');
      const newData = await response.json();
      return newData;
    } catch (err) {
      setError(err.message);
      return [];
    }
  };

  const loadMore = async () => {
    if (error) return;
    const newData = await fetchData(page + 1);
    if (newData.length > 0) {
      setData((prevData) => [...prevData, ...newData]);
      setPage((prevPage) => prevPage + 1);
    } else {
      setHasMore(false);
    }
  };

  const handleRefresh = async () => {
    setIsRefreshing(true);
    setError(null);
    const initialData = await fetchData(1);
    setData(initialData);
    setPage(1);
    setHasMore(true);
    setIsRefreshing(false);
  };

  useEffect(() => {
    fetchData(1).then(setData);
  }, []);

  return (
    <SafeAreaView style={styles.container}>
      <InfiniteScroll
        data={data}
        renderItem={({ item }) => (
          <View style={styles.item}>
            <Text style={styles.title}>{item.title}</Text>
            <Text>{item.body}</Text>
          </View>
        )}
        keyExtractor={(item) => item.id.toString()}
        loadMore={loadMore}
        hasMore={hasMore}
        onRefresh={handleRefresh}
        isRefreshing={isRefreshing}
        error={error}
        errorComponent={<Text style={styles.errorText}>{error}</Text>}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, padding: 16 },
  item: { padding: 16, borderBottomWidth: 1, borderBottomColor: '#ccc' },
  title: { fontSize: 16, fontWeight: 'bold' },
  errorText: { textAlign: 'center', color: 'red', marginVertical: 20 },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

Props

Prop Type Description
data Array The array of data items to render.
renderItem Function Function to render each item in the list.
keyExtractor Function Function to extract a unique key for each item.
loadMore Function Function to load more data. Should return a Promise.
hasMore Boolean Whether there is more data to load.
loaderComponent React.ReactNode Custom loader component to display while loading more data.
listEmptyComponent React.ReactNode Component to display when the list is empty.
onRefresh Function Function to refresh the list. Should return a Promise.
isRefreshing Boolean Whether the list is currently refreshing.
error String or null Error message to display if data fetching fails.
errorComponent React.ReactNode Custom error component to display when there’s an error.

Customization

Custom Loader

<InfiniteScroll loaderComponent={<MyCustomLoader />} // other props />
Enter fullscreen mode Exit fullscreen mode

Custom Error Component

<InfiniteScroll errorComponent={<MyCustomErrorComponent />} // other props />
Enter fullscreen mode Exit fullscreen mode

Custom Empty List Component

<InfiniteScroll listEmptyComponent={<MyCustomEmptyComponent />} // other props />
Enter fullscreen mode Exit fullscreen mode

Contributing

Contributions are welcome! Follow these steps:

  1. Fork the repository.
  2. Create a new branch:
   git checkout -b feature/YourFeatureName
Enter fullscreen mode Exit fullscreen mode
  1. Commit your changes:
   git commit -m 'Add some feature'
Enter fullscreen mode Exit fullscreen mode
  1. Push to the branch:
   git push origin feature/YourFeatureName
Enter fullscreen mode Exit fullscreen mode
  1. Open a pull request.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Author

Babar Bilal

If you find this library useful, please ⭐️ the repository on GitHub!

GitHub: https://github.com/babarbilal56

LinkedIn: www.linkedin.com/in/babarbilal56

Top comments (0)