Refresh in React Native ScrollView
Published On: 2024-07-11
Posted By: Harish

Sometimes we may need to get the fresh updated data from an API to show in a scrollview. We can use a button to get data whenever we manually press the button.
Or we can use RefreshControl of scrollview to get the updated data by pulling down scrollview content when scroll y-axis position is at 0. This functionality only works with vertical scrollview.
Let's see how this refresh works with an example.
Create A New Project
Create a new react-native project by using npx. Check documentation for creating a new react native project.
npx react-native@latest init ScrollViewRN
Example Implementation
We will create a simple vertical scrollview with color blocks which adds a new color block on refresh.
Import and add ScrollView
with few scrollable color blocks.
//App.tsx
...
import { View, ScrollView } from 'react-native';
...
<ScrollView
contentContainerStyle={styles.content_container}
>
{
colors
.map((color: string) => {
return (
<View
key={color}
style={[
styles.view,
{
backgroundColor: color
}
]}
>
</View>
)
})
}
</ScrollView>
...
If we run the app,
#for Android
npx react-native run-android
#for ios
npx react-native run-ios
Color blocks list can be seen on render.
For this example, we will add a new color red
to the list whenever we refresh the scrollview.
For that, we have to import RefreshControl
component from react-native and add it to scrollview's refreshControl prop.
The RefreshControl component requires a refreshing
prop, which accepts boolean values and is used to show or hide the loading indicator. Another one is the onRefresh
callback to call a function to update scrollview data.
...
import { RefreshControl } from 'react-native';
...
<ScrollView
...
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
/>
}
>
...
</ScrollView>
...
Please refer to the complete code block below for code.
For refreshing
prop, we used useState
to store the state of the indicator. And for the onRefresh
function, we are updating the colors list with a new one inside a timeout function to delay the process. This timeout function is completely for this tutorial and not needed in general.
If we reload the metro and pull down the list, we can see a loading indicator and after 1 second
we will see a new color block added to the list.

Change Refresh Indicator Color
We can change the default color of the refresh indicator to our own color. But different props are required for different platforms.
For iOS, tintColor prop and for Android colors prop are to be used.
The tintColor
accepts a single color whereas RefreshControl's colors
prop accepts an array of colors.
Let's add indicator color for iOS. Add tintColor
prop to scrollview with a color. And run the app in an iPhone simulator or device.
If we refresh the scrollview, we will see a green indicator.

For Android OS, add colors
prop with an array of colors. Longer duration to refresh shows different colors listed in the array.
For this, let's increase the timeout time to 5 Seconds
. Add colors
prop to scrollview and pull down to refresh in android device or emulator.
...
<ScrollView
...
refreshControl={
<RefreshControl
...
tintColor='green'
colors={['blue', 'green', 'red']}
/>
}
>
...
</ScrollView>
...
We will notice that the indicator changes its color to listed colors till the data refreshes.

Change Refresh Indicator Position
If you want to shift the refresh indicator's position, use progressViewOffset prop. This prop accept number to shift the indicator's position vertically.
Complete code of our example,
//App.tsx
import React, { useState, useCallback } from "react";
import {
Text,
StyleSheet,
SafeAreaView,
StatusBar,
View,
ScrollView,
RefreshControl,
} from "react-native";
let defaultColors = [
'orange',
'green',
'blue',
'maroon',
'violet',
'darkorange',
'gold',
'darkgreen',
'aquamarine',
'cadetblue'
];
export default function App() {
const [refreshing, setRefreshing] = useState(false);
const [colors, setColors] = useState(defaultColors);
const onRefresh = useCallback(() => {
setRefreshing(true);
setTimeout(() => {
setColors(prev => ["red", ...prev]);
setRefreshing(false);
}, 1000);
}, []);
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
<StatusBar
barStyle="dark-content"
/>
<View style={styles.container}>
<Text style={styles.text}>
ifelsething.com
</Text>
<Text style={styles.text}>
refresh in scrollview
</Text>
<ScrollView
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
//progressViewOffset={10}
/>
}
contentContainerStyle={styles.content_container}
>
{
colors.map((color: string, index: number) => {
return (
<View
key={index}
style={[
styles.view,
{
backgroundColor: color
}
]}
/>
)
})
}
</ScrollView>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
margin: 10,
gap: 20
},
text: {
fontSize: 15,
color: 'black',
fontStyle: 'italic'
},
content_container: {
gap: 10
},
view: {
width: '100%',
height: 200,
borderRadius: 10,
}
});