Waldo sessions now support scripting! – Learn more
App Development

Infinite scrolling React Native Apps for performance optimization

Llamdo
Llamdo
Infinite scrolling React Native Apps for performance optimization
January 23, 2020
11
min read

What we’ll build

We’ll build an infinite scrolling user listing application using the React Native FlatList component.

Prerequisites

To follow along in this post, here are a few prerequisites to note:

  • Working knowledge of React or React Native
  • XCode or Android studio installed
  • Node 10+ Installed

Getting started

We’re going to start with a few installations for those using React Native for the first time. If this is your first time working with React Native, be sure to install the required packages and follow these steps accordingly:

1. Install the React Native CLI tool using npm like so:


npm install -g react-native-cli

Afterwards, go ahead and run these React Native commands to create and start a new project.

2. Create the animations project and start the server:


react-native init scrolling_demo

cd scrolling_demo && npx react-native run-ios // Start the iOS simulator
// OR
cd scrolling_demo && npx react-native run-android // Android the android emulator

If you have Xcode or Android Studio installed then the commands above will run the project and you should have the simulator show up on the screen like this:

Install dependencies

Before we start, It’s important to first install the necessary dependencies for this project, in our case, we only need: Axios — for making API requests to fetch users and React Native Elements — for the custom card components we’ll use in this project.


npm i --save axios
npm i react-native-elements --save
npm i --save react-native-vector-icons // required by react-native-elements

Set up the Users component

In the root directory of the sample project we created, create a new src/components/Users.js file. In this file, first, we fetch the users that we want to display here from the Github Users API. To do that, we define a fetchUsers() function that will make a call to the API and initially get us a list of 10 users:


import React, {Component} from 'react';
import axios from 'axios';

class Users extends Component {
constructor(props) {
  super(props);
  this.state = {
    users: [],
    page: 1,
    error: null,
  };
}
fetchUsers = () => {
  const {page} = this.state;
  axios
    .get(`https://api.github.com/users?since=${page}&per_page=10`)
    .then(response => {
      this.setState({
        users: this.state.users.concat(response.data),
      });
    })
    .catch(error => {
      this.setState({error: error});
    });
};
}

export default Users;

Here, we first defined three state properties, users to hold the users data fetched from the API, page to denote which page of the users API we are fetching, and error to handle error cases.

Then we defined a fetchUsers() function that uses Axios to fetch users and update our users array with the fetched data. Finally, we want to call this function when our app is mounted so let’s do that with the componentDidMount() lifecycle method:


componentDidMount() {  
this.fetchUsers(this.state.page);
}

Now when the app loads, we’ll have the users fetched in our application, we can go ahead and update the app UI with the data.

Rendering The Fetched User

React Native provides us with a <FlatList/> UI component that handles the rendering of a simple flat list such as this one, in a performant way. Here, we’ll use it to display the list of users.


import React, {Component} from 'react';
import {ScrollView, View, Text, FlatList, Image} from 'react-native';
import {Card} from 'react-native-elements';
import axios from 'axios';
class Users extends Component {
constructor(props) {
  super(props);
  this.state = {
    users: [],
    page: 1,
    error: null,
  };
}
fetchUsers = () => {
// fetch users here
};
componentDidMount() {
  this.fetchUsers(this.state.page);
}
render() {
  return (
<FlatList
        contentContainerStyle={{
          backgroundColor: '#FBFBF8',
          alignItems: 'center',
          justifyContent: 'center',
          marginTop: 15,
        }}
        data={this.state.users}
        keyExtractor={user => user.id.toString()}
        renderItem={({item}) => (
<View
            style={{
              marginTop: 10,
            }}>
<Card>
<Image
                style={{width: 200, height: 100}}
                source={{uri: item.avatar_url}}
              />
<Text>{item.login}</Text>
</Card>
</View>
        )}
      />
  );
}
}
export default Users;

The <FlatList/> component provides us with a good number of props through which we customise its behaviour to suit our needs. The two major props that are always required are the data and the renderItem props.
We use the data prop to supply the data content we intend to render in the

FlatList, and then use the renderItem prop to de-structure the data and render each item. In due time, we’ll use other features of the <FlatList/> component to implement infinite scrolling feature that allows user to scroll through several pages of this application.

Run The App
Save the current changes and run the app with any of the commands below and we’ll get the following visual output:


//In the terminal, run:
npx react-native run-ios //OR
npx react-native run-android

Infinite Scroll

Now that we have the initial functionality set up, it’s time to implement the infinite scroll feature. Thankfully, the <FlatList/> component also gives us the ability to do this. Among its other features, Scroll loading is one performant feature that comes with the <FlatList/> component. It makes it possible for us to load more content on-demand.

In our case, we will automate the demand such that whenever a user scrolls down to a certain extent in our app, we’ll request for more content. This will be possible using the FlatList components’ onEndReached prop and also the onEndReachedThreshold prop.

FlatList Scroll Props
The onEndReached prop is a callback function that fires when the onEndReachedThreshold is reached. The onEndReachedThreshold prop is a number that indicates at which position of the page the list will be at for the onEndReached callback to fire.

Basically what this means is that we use the onEndReachedThreshold to specify a value that will correspond with the content of the page, when the user scrolls to that value, we trigger the onEndReached callback and fetch more content, hence, infinite scroll.

Next, define the function that gets called when the set threshold is reached. Call it fetchMoreUsers(), that’s exactly what it’ll do:


fetchMoreUsers = () => {
  this.setState(
    prevState => ({
      page: prevState.page + 100,
    }),
    () => {
      this.fetchUsers();
    },
  );
};

Here, we update the value of the page variable to fetch a different page of users from the API and finally, we call the fetchUsers() function. This will then fetch the new page of users and render them on our FlatList. How do we tell our application to call the fetchMoreUsers() function? You probably guessed right, the onEndReached prop. Let’s pass in those new props to our <FlatList /> component.


onEndReached={this.fetchMoreUsers}
onEndReachedThreshold={0.5}

This way, when a user scrolls down half the current page, the fetchMoreUsers() function is called to load more content, hence, infinite scrolling achieved. Now if we run the app again, we get the infinite scrolling ability:

More Performance Optimizations

If you’re dealing with a large list that may often take time to load or update in a virtualized list component (FlatList) It may have some performance costs since the component will update on every state change of any component. The advised approach to handling such a situation is to either use a PureComponent or use the shouldComponentUpdate() lifecycle method.


class Users extends React.PureComponent {
// content
}

Conclusion

Infinite scrolling is a not so popular feature in both web and mobile applications with great performance and usability gains. In this project, we have demonstrated how to implement it using the FlatList component in a React Native project to give you more practical experience of using this feature. You can learn more about FlatList in the documentation. To dig the source, find the project repository here.Infinite scrolling is a very important piece of functionality in modern mobile applications. When done right, it improves the performance of the application, optimizes render calls and offers an overall great user experience.

Why? because it makes loading a predefined amount of content possible on page load, and only fetching more content on-demand. In this post, we’ll show you how to implement this functionality while building a React Native app. Learn more here.

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.