Here is the rewritten article:
Enhancing Mobile App Performance: Implementing Pull-to-Refresh and Scroll-to-Refresh in React Native
In today’s digital landscape, users expect seamless and intuitive mobile experiences. One crucial aspect of achieving this is implementing pull-to-refresh and scroll-to-refresh functionality in mobile applications. In this article, we’ll explore how to integrate these features in a React Native application using a FlatList component. Additionally, we’ll discuss customizing the RefreshControl component to enhance the user experience.
Project Setup
To follow along with this tutorial, you can refer to the accompanying GitHub repository, which contains all the code used in this article. Alternatively, you can generate a new Expo React Native application by following the provided guide.
Creating a Custom Hook
A React Hook is a special function that allows us to manage states without writing a class or a component. We’ll set up a custom Hook to make API calls to a server to fetch data and store it in a state to be used in our components. To start, install Axios by running the following command in the terminal:
npm install axios
Next, open the hooks/useFetchUser.js
file, import necessary dependencies, and declare some constants. Then, create the useFetchUser
Hook and declare some states:
import { useState, useEffect } from 'eact';
import axios from 'axios';
const FETCH<em>RESULTS = 10;
const MAX</em>LENGTH = 20;
const useFetchUser = () => {
const [users, setUsers] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const [currentPage, setCurrentPage] = useState(1);
const getUsers = async (currentPage, isTop) => {
try {
const response = await axios.get(<code>https://randomuser.me/api?page=${currentPage}&results=${FETCH_RESULTS}</code>);
const data = response.data.results;
if (isTop) {
setUsers([...data,...users]);
} else {
setUsers([...users,...data]);
}
setSuccess(true);
} catch (error) {
setErrorMessage(error.message);
} finally {
setIsLoading(false);
}
};
return { users, isLoading, success, errorMessage, getUsers };
};
export default useFetchUser;
<p><strong>Setting Up the Loader Component</strong></p>
<p>The loader component will be used to indicate when the API fetching is in progress. To build the loader, we need to import necessary dependencies and then pass the <code>isLoading</code> and <code>withText</code> parameters.</p>
<p>“`
import React from ‘eact’;
import { ActivityIndicator, View, Text } from ‘eact-native’;
const Loader = ({ isLoading, withText }) => {
if (!isLoading) return null;
return (
{withText &&
);
};
export default Loader;
Building the Item Component
The Item
component is used to represent the rendered item of the FlatList
component. The Item
function accepts item
and index
parameters and returns a View
with an Image
and a second View
component.
```
import React from 'eact';
import { View, Image, Text } from 'eact-native';
const Item = ({ item, index }) => {
return (
<View style={{ flex: 1, flexDirection: 'row', padding: 16 }}>
<Image source={{ uri: item.picture.large }} style={{ width: 50, height: 50, borderRadius: 25 }} />
<View style={{ flex: 1, justifyContent: 'center', paddingHorizontal: 16 }}>
<Text>{item.name.first} {item.name.last}</Text>
<Text>{item.email}</Text>
</View>
</View>
);
};
export default Item;
</code></pre>
<p><strong>Setting Up Pull-to-Refresh Functionality</strong></p>
<p>We'll create a <code>TopLoader</code> screen to demonstrate how to handle pull-to-refresh at the top of the list. To start, import necessary dependencies, including the <code>FETCH_RESULTS</code>, <code>useFetchUser.js</code>, <code>Item.jsx</code>, and <code>Loader.jsx</code> files.</p>
<p>```
import React, { useState, useEffect } from 'eact';
import { FlatList, View, Text } from 'eact-native';
import useFetchUser from '../hooks/useFetchUser';
import Item from '../components/Item';
import Loader from '../components/Loader';
const TopLoader = () => {
const { users, isLoading, success, errorMessage, getUsers } = useFetchUser();
const [refreshing, setRefreshing] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
useEffect(() => {
getUsers(currentPage, true);
}, [currentPage]);
const onRefresh = () => {
setRefreshing(true);
getUsers(currentPage, true);
};
const scrollToItem = (index) => {
flatListRef.scrollToIndex({ animated: true, index });
};
return (
}
keyExtractor={(item) => item.email}
onRefresh={onRefresh}
refreshing={refreshing}
onScrollToIndexFailed={(info) => {
const wait = new Promise((resolve) => setTimeout(resolve, 500));
wait.then(() => {
scrollToItem(info.index);
});
}}
/>
{isLoading && }
{errorMessage && }
);
};
export default TopLoader;
Customizing the Refresh Control
You can customize the refresh control by providing certain properties. These properties allow you to modify the background color, text color, and other aspects of the loader offered by the component.
}
/>
Setting Up Scroll-to-Refresh Functionality
The concept behind scroll-to-refresh is that when users reach the bottom of a list and continue dragging the list downward, it will automatically update by fetching the next set of results.
```
import React, { useState, useEffect } from 'eact';
import { FlatList, View, Text } from 'eact-native';
import useFetchUser from '../hooks/useFetchUser';
import Item from '../components/Item';
import Loader from '../components/Loader';
const BottomLoader = () => {
const { users, isLoading, success, errorMessage, getUsers } = useFetchUser();
const [currentPage, setCurrentPage] = useState(1);
const [loadingMore, setLoadingMore] = useState(false);
useEffect(() => {
getUsers(currentPage, false);
}, [currentPage]);
const loadMoreItems = () => {
setLoadingMore(true);
setCurrentPage(currentPage + 1);
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<FlatList
data={users}
renderItem={({ item, index }) => <Item item={item} index={index} />}
keyExtractor={(item) => item.email}
onEndReached={loadMoreItems}
onEndReachedThreshold={0.5}
ListFooterComponent={<Loader withText />}
/>
{isLoading && <Loader withText />}
{errorMessage && <Text style={{ color: 'ed' }}>{errorMessage}</Text>}
</View>
);
};
export default BottomLoader;
</code></pre>
<p><strong>Combining the Refresh Functionalities</strong></p>
<p>Next, we'll streamline the pull-to-refresh functionality and scroll-to-refresh functionality into a single <code>FlatList</code> component.</p>
<p>```
import React, { useState, useEffect } from 'eact';
import { FlatList, View, Text } from 'eact-native';
import useFetchUser from '../hooks/useFetchUser';
import Item from '../components/Item';
import Loader from '../components/Loader';
const Combined = () => {
const { users, isLoading, success, errorMessage, getUsers } = useFetchUser();
const [currentPage, setCurrentPage] = useState(1);
const [refreshing, setRefreshing] = useState(false);
const [loadingMore, setLoadingMore] = useState(false);
useEffect(() => {
getUsers(currentPage, true);
}, [currentPage]);
const onRefresh = () => {
setRefreshing(true);
getUsers(currentPage, true);
};
const loadMoreItems = () => {
setLoadingMore(true);
setCurrentPage(currentPage + 1);
};
return (
}
keyExtractor={(item) => item.email}
onRefresh={onRefresh}
refreshing={refreshing}
onEndReached={loadMoreItems}
onEndReachedThreshold={0.5}
ListFooterComponent={ }
/>
{isLoading && }
{errorMessage && }
);
};
export default Combined;
```
By following this tutorial, you should now have a React Native application that implements pull-to-refresh and scroll-to-refresh functionality using a FlatList
component. Additionally, you've learned how to customize the refresh control component to enhance the user experience.