React Native is without any doubt a strong and powerful solution. It opens the world of cross-platform app development for a much wider audience of software engineers who aren’t familiar with native technologies. But it might at the same time be quite difficult to implement complex things when you’ve just started learning. In this short tutorial, I want to give a step-by-step guide on how to implement one of them — infinite scroll.
Ok, so let’s begin. For the purposes of this short tutorial, I’ll use the Expo library — it’s quite handy when it comes to building simple React Native applications. So, make sure the following is installed on your machine:
First of all, open the console and create a basic minimal app using the expo executable:
expo init infinite_scroll
. It offers to choose a template from which the application will be created — just go with the blank option, that’s enough to achieve our today’s goal.Now we need to wait a tiny bit while
expo
is preparing our app and installing all the underlying libraries. Once it’s done we have a fully functional React Native application that we can launch by calling expo start
.Expo offers a very handy option — to run your application in the iOS simulator. That’s how our app looks like when we launch it for the first time:
Now we’re all set for development — let’s write some code. Open the app directory in your favorite code editor and find there in the root a file named
App.js
. App.js
is the entry point of the application, and that’s how it looks like at the very beginning:import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Our goal is to implement an infinite scroll. One of the easiest ways is to display a long list of simple elements and make them properly scrollable. Further in development, you could connect your app to a data source, like an external API, or a local data storage, but we will go with a simple array of elements right in the app code:
const data = [
{id: 1, text: 'One'}
]
The second thing we should define is how we will display each of the elements. Since we are working with React Native, we have all the powers of React at our service, so we need to define a new view, that will represent a single element. For that, we’ll define a new
const Item
and use the functional approach to return a <View>
component with a <Text>
component inside:const Item = ({item}) => {
return (
<View>
<Text>{item.text}</Text>
</View>
);
}
Those are all just standard React Native components, so you don’t need to connect any third-party libraries to your project.
It’s also a good idea to style our element a bit to make it look nicer, for example as a white rectangle with a shadow so it’ll look like it’s levitating on top of the background.
Here’s the final code with the styling applied:
...
const data = [
{id: 1, text: 'One'}
]
const Item = ({item}) => {
return (
<View style={[styles.item, styles.shadow]}>
<Text>{item.text}</Text>
</View>
);
}
...
const styles = StyleSheet.create({
item: {
backgroundColor: '#fff',
padding: 20,
marginHorizontal: 10,
marginBottom: 3.5,
flexDirection: 'row'
},
shadow: {
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 10
},
shadowOpacity: 0.47,
shadowRadius: 9,
}
});
After that, we’re almost all set to see the first list element gently floating over the background of our iOS Simulator. And the last thing due is actually the core thing to make our list infinitely scrollable — the
<FlatList>
component. You can find more about it in the official documentation.data
, where the data source should be passed. In our case, it’s a constant with the same name that we’ve defined on an earlier step;renderItem
, to which we pass the defined earlier Item
constant and which makes sure to render each of the data
;keyExtractor
that is responsible for finding unique keys in your data set — they’re required for proper rendering of elements....
const List = () => {
return (
<FlatList
contentContainerStyle={styles.list}
data={data}
renderItem={Item}
keyExtractor={item => item.id}
/>
);
}
export default function App() {
return (
<List />
);
}
const styles = StyleSheet.create({
list: {
paddingVertical: 30,
justifyContent: 'flex-start'
}
});
After applying those changes to the App.js, we can see first satisfying and encouraging results in the Simulator:
Now that we have everything in place for multiple list elements, let’s just add them — The Mighty Eighteen items that will take all the Simulator screen and even more. And that’s exactly what we need to test our implementation of the infinite scroll.
const data = [
{id: '1', text: 'One'},
{id: '2', text: 'Two'},
{id: '3', text: 'Three'},
{id: '4', text: 'Four'},
{id: '5', text: 'Five'},
{id: '6', text: 'Six'},
{id: '7', text: 'Seven'},
{id: '8', text: 'Eight'},
{id: '9', text: 'Nine'},
{id: '10', text: 'Ten'},
{id: '11', text: 'Eleven'},
{id: '12', text: 'Twelve'},
{id: '13', text: 'Thirteen'},
{id: '14', text: 'Fourteen'},
{id: '15', text: 'Fifteen'},
{id: '16', text: 'Sixteen'},
{id: '17', text: 'Seventeen'},
{id: '18', text: 'Eighteen'},
]
The last thing that will wrap it all up is the
<SafeAreaView>
React Native component that ensures its enclosed content will not conflict with any other components around it. Please see more in the official documentation.Here’s the final state of the
App.js
:import React from 'react';
import { StyleSheet, Text, View, FlatList, SafeAreaView } from 'react-native';
const data = [
{id: '1', text: 'One'},
{id: '2', text: 'Two'},
{id: '3', text: 'Three'},
{id: '4', text: 'Four'},
{id: '5', text: 'Five'},
{id: '6', text: 'Six'},
{id: '7', text: 'Seven'},
{id: '8', text: 'Eight'},
{id: '9', text: 'Nine'},
{id: '10', text: 'Ten'},
{id: '11', text: 'Eleven'},
{id: '12', text: 'Twelve'},
{id: '13', text: 'Thirteen'},
{id: '14', text: 'Fourteen'},
{id: '15', text: 'Fifteen'},
{id: '16', text: 'Sixteen'},
{id: '17', text: 'Seventeen'},
{id: '18', text: 'Eighteen'},
]
const Item = ({item}) => {
return (
<View style={[styles.item, styles.shadow]}>
<Text>{item.text}</Text>
</View>
);
}
const List = () => {
return (
<FlatList
contentContainerStyle={styles.list}
data={data}
renderItem={Item}
keyExtractor={item => item.id}
/>
);
}
export default function App() {
return (
<SafeAreaView style={styles.container}>
<List />
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
},
list: {
paddingVertical: 30,
justifyContent: 'flex-start'
},
item: {
backgroundColor: '#fff',
padding: 20,
marginHorizontal: 10,
marginBottom: 3.5,
flexDirection: 'row'
},
shadow: {
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 10
},
shadowOpacity: 0.47,
shadowRadius: 9,
}
});
And that’s how the scrolled down feed in the app looks like:
In the next tutorial, we'll add a button floating on top of our items list and make that button adding even more items to the list.
Previously published at https://medium.com/@mulev/digesting-react-native-one-piece-at-a-time-infinite-scroll-1b18a15c556