react-native-custom-pull-refresh
v0.1.1
Published
react-native-custom-pull-refresh is a lightweight and highly customizable pull-to-refresh component for React Native designed for smooth gesture handling and consistent cross-platform behavior
Maintainers
Readme
react-native-custom-pull-refresh
React Native Custom Pull Refresh is a high-performance, lightweight refresh-control engine designed to bring professional, 60fps animations to your scrollable components.
By leveraging a hybrid architecture—utilizing PanResponder for fluid iOS gestures and native view detection for Android—it ensures your custom animations stay perfectly synced and feel "native" on every device.
🚀 Key Features
- Hybrid Gesture Engine: Optimized
PanResponderlogic for iOS combined with native Android view integration to prevent "scroll hijacking." - Reanimated Powered: Built from the ground up to work with
SharedValues, allowing for complex UI effects without crossing the bridge. - Normalized Progress (0 to 1): Easily build sophisticated parallax, scaling, or fading header effects (like scaling logos) using a simple, real-time progress value.
- Smart Resting State: Includes built-in support for a "hang" position, allowing the list to snap smoothly to a loading state while your data fetches.
- Lightweight & Flexible: Designed to wrap
FlatListorScrollViewwith minimal overhead and maximum customizability.
🛠 Why this library?
Standard pull-to-refresh wrappers often struggle with platform-specific "jank"—Android frequently suffers from gesture conflicts, while iOS can feel rigid. This library solves that by treating each platform differently under the hood while providing you with a single, clean API to animate your UI.
1. Installation
npm install react-native-custom-pull-refreshThis library requires react-native-reanimated. Make sure all steps for installing it are done as described in the official documentation.
npm install react-native-reanimated2. Components Exported
The library exports the following components to be used:
PullRefreshFlatListPullRefreshScrollView
import {
PullRefreshFlatList,
PullRefreshScrollView,
} from 'react-native-custom-pull-refresh';3. Example
Here is an example code for PullRefreshFlatList as shown in the example app. The same usage applies for PullRefreshScrollView.
For a complete working example, please check the Example App reference in the repository.
import { useState } from 'react';
import type { ListRenderItem } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import { PullRefreshFlatList } from 'react-native-custom-pull-refresh';
import { useSharedValue } from 'react-native-reanimated';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { h } from '../../src/utils';
import { AnimtedLogo } from './components';
type ListItem = { id: string; title: string };
const SAMPLE_DATA: ListItem[] = Array.from({ length: 20 }, (_, i) => ({
id: `item-${i}`,
title: `Item ${i + 1}`,
}));
const MAX_PULL_HEIGHT = h(20);
export default function App() {
const [refreshing, setRefreshing] = useState(false);
const [data] = useState(SAMPLE_DATA);
const progress = useSharedValue(0);
const onRefresh = () => {
setRefreshing(true);
setTimeout(() => {
setRefreshing(false);
}, 1500);
};
const renderItem: ListRenderItem<ListItem> = ({ item }) => (
<View style={styles.item}>
<Text style={styles.itemText}>{item.title}</Text>
</View>
);
return (
<SafeAreaProvider>
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
<PullRefreshFlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
numColumns={2}
columnWrapperStyle={styles.columnWrapper}
contentContainerStyle={styles.contentContainer}
showsVerticalScrollIndicator={false}
onRefresh={onRefresh}
refreshing={refreshing}
bounces={false}
maxPullHeight={MAX_PULL_HEIGHT}
containerBackgroundColor={'white'}
style={styles.list}
onPullDownProgress={(offset) => {
'worklet';
progress.value = offset;
}}
refreshBackgroundColor={'#D3D3D3'}
renderPullView={
<AnimtedLogo
pullDownPosition={progress}
refreshing={refreshing}
/>
}
/>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
safeArea: {
flex: 1,
backgroundColor: 'white',
},
list: {
marginTop: 16,
},
columnWrapper: {
justifyContent: 'space-between',
paddingHorizontal: 16,
gap: 12,
marginBottom: 12,
},
contentContainer: {
paddingBottom: 24,
},
item: {
flex: 1,
aspectRatio: 1,
backgroundColor: '#f0f0f0',
borderRadius: 8,
alignItems: 'center',
justifyContent: 'center',
},
itemText: {
fontSize: 14,
color: '#666',
},
});4. Props
The pull-to-refresh components (PullRefreshFlatList and PullRefreshScrollView) accept the following extra props in addition to their default React Native props:
| Prop | Type | Default | Description |
| -------------------------- | -------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| refreshing | boolean | Required | Whether the view should be indicating an active refresh. |
| onRefresh | () => void | Required | Called when the view starts refreshing. |
| renderPullView | React.ReactNode | Required | A custom React Node that renders behind the list when pulling down. (render your custom pull view here) |
| onPullDownProgress | (offset: number) => void | Optional | callback that fires continuously with a progress value (between 0 and 1) as the user pulls down. Can be used for custom worklet animations. |
| maxPullHeight | number | Optional | Maximum height the pull view can be dragged down (in pixels). |
| refreshBackgroundColor | string | Optional | Background color behind the pulled view. |
| containerBackgroundColor | string | Optional | Background color of the scroll view / flat list overlay container. |
Note: All other default props belonging to FlatList (for PullRefreshFlatList) or ScrollView (for PullRefreshScrollView) are also fully supported and passed down directly!
License
MIT
