React Native Basics: How to Use the ListView Component
ListView — A core component designed for efficient display of vertically scrolling lists of changing data.
Basically it’s a way to create an efficient scrolling component. It’s driven by a data blob and, theoretically, can be infinitely long. Whereas the other core scrollable component, ScrollView, may run into performance issues for very long lists. ListView actually uses a ScrollView as it’s scrollable component behind the scenes, by default, so you can do all of this with a ScrollView if you want to build your own abstraction. ListView is an abstraction that adds a lot of nice things and optimization on top of ScrollView.
So what’s the most basic way to use a ListView? You’ll need two things to effectively use this component: a ListView.DataSource and a renderRow function that returns a component.
A ListView.DataSource does a lot of things behind the scenes that allow us to have an efficient data blob that the ListView component can understand, all from a simple array. To start we’re just going to use it to handle the rows but you’ll see later on how we can use it for our section headers too.
The renderRow function simply returns a component that, well, renders the row. It’s passed the data for that row as a prop to the function. We’ll expand on that later.
You can see an extremely basic version of a ListView here:
For the remainder of the tutorial I’ll be using a more robust data set, courtesy of Random User Generator. You can access my exact data set here.
Before going any deeper let’s break that renderRow function out into its own component and make it a little bit better looking.
This is pretty straight forward — renderSeparator renders a separator between components in your list. Why create a different component rather than tacking on a border bottom on the component returned by renderRow? Because renderSeparator is smart! It won’t render the separator on the last element in the section. So how do we use it?
So all we’re doing there is adding a style property for our separator and then adding renderSeparator to the ListView, which returns a valid React component. The rowId is passed as a prop in that function which works well for a key (otherwise RN will throw a warning).
A header is, as you may have guessed, a component that is rendered at the top of your ListView. It’s guaranteed to always be the first thing. A good use case for this, in the context of our people list, would be a search bar. Let’s build it.
So that’s a very basic search bar (that doesn’t actually do anything). Let’s wire it into our ListView.
It’s not beautiful (I never said I was a designer) but we’ve now got a nice search bar that lives at the top of our ListView.
Much like the header sticks to the top of the list, the footer sticks to the bottom. This would be a good place to put a “Load More” button or, if you’ve got infinite scrolling, a loading indicator to keep up with the lightning scrolling of your users. Implementing this is going to be just like using a header. We’ll create our footer component then tell our ListView to render it.
Looking more and more like… a list of people!
Sticky Section Headers
So this is a part that I think is really cool but sadly not very well documented. We can put our content into sections and label it appropriately. Our labels/section headers will then automatically stick to the top until the next section comes up during scrolling. I’m not going to cover what exactly is happening to create our data but if you want a deeper understanding I would suggest reading this blog post.
First, let’s create our SectionHeader component. This is the easiest part.
This next part is the most complex. I tried to write it out but couldn’t convey my point very well so I decided to just add comments to my code to hopefully get the point across. Please let me know if you’ve got any questions.
The gist of it here is that we’re taking our data and splitting it into sections, alphabetically. To do that we need 3 things: an array of row ids, an array of section ids, and an object representing our data. The data object will store whatever data should be passed to our row or section. The section ids array simply stores an array of strings that align with the appropriate key in the data blob. The array of row ids is actually an array of arrays. The top level aligns with the section ids and then the nested array holds the actual row id, again aligning with a key in the data object. Hopefully the annotations properly demonstrate what I’m trying to do.
Finally we need to use our formatData function and render our section headers.
Notice the changes in constructor we have to format our data a bit differently to get everything to work with our sections. I’m not going to cover it in depth because it’s been the same for all of my projects to date and that configuration will likely work for you as well.
And there you have it! You’ve now got section headers that will stick to the header as you scroll through the section and be replaced as the next section is hit.
That’s the basics of using ListView. There are numerous other things you can do with it and I would suggest you checking out the docs for further information.
Did you find this helpful? Are you interested in learning more about React Native? Check out my free course on building an app with React Native! It’s a comprehensive overview of all you’ll need to know.
Some of the things you’ll want to do with a ListView may already be done and open sourced. I’d suggest doing a bit of research to save some time!