Build an image browsing App with React Native (4) — RecyclerListView
React Native brings React’s declarative UI framework to iOS and Android. With React Native, you use native UI controls and have full access to the native platform. (https://github.com/facebook/react-native)
And this is the 4th article of this tutorial about how to build an image browsing App with React Native. So I suppose you have read the prior parts of it.
There are the links to these prior chapters.
Actually, we have implemented all features of such an image browsing app, including displaying images in a FlatList
, fetching data from backend API, saving data in persistent storage, save data in a global state store with Redux, navigating from one route to another route with react-navigation
. So in this article, I would just have some improvements like using RecyclerListView
to display the images instead of using FlatList.
What is RecyclerListView?It is a high-performance listview for React Native and Web with support for complex layouts. JS only with no native dependencies, inspired by both RecyclerView on Android and UICollectionView on iOS.
RecyclerListView uses “cell recycling” to reuse views that are no longer visible to render items instead of creating new view objects. The creation of objects is very expensive and comes with a memory overhead which means as you scroll through the list the memory footprint keeps going up. Releasing invisible items off memory is another technique but that leads to the creation of even more objects and a lot of garbage collections. Recycling is the best way to render infinite lists that do not compromise performance or memory efficiency.
It would be able to do all things the FlatList can do, but with better performance.
Add RecyclerListView package
Firstly we need to add a new package to support RecyclerListView
by running
yarn add recyclerlistview
and you would find a new dependency is added to the Package.json
in your project.
Create RecyclserList component
Then let’s create a new file, RecyclerList.tsx
in the home
folder, and add the following code
import React from 'react';
import {
RecyclerListView,
DataProvider,
LayoutProvider,
Dimension,
} from 'recyclerlistview';
import {StyleSheet, StatusBar, Dimensions} from 'react-native';
import Item from './Item';const getWindowWidth = () =>
Math.round(Dimensions.get('window').width * 1000) / 1000 - 6;
const RecyclerList = ({
data,
nextPage,
navigation,
}: {
data: Array<Photo>;
nextPage: () => void;
navigation: any;
}): JSX.Element => {
console.log(
'RecyclerList',
data.map(item => item.id),
);const renderItem = (type: string | number, data: any) => (
<Item photo={data} navigation={navigation} />
);
const dataProvider = new DataProvider((r1, r2) => {
return r1 !== r2;
}).cloneWithRows(data);
const layoutProvider = new LayoutProvider(
index => {
return JSON.stringify({
width: data[index].width,
height: data[index].height,
});
},
(type: string | number, dim: Dimension) => {
switch (type) {
case 'VSEL':
dim.width = getWindowWidth() / 2;
dim.height = 150;
break;
default:
if (typeof type === 'string') {
const {width, height} = JSON.parse(type);
dim.width = getWindowWidth() / 2;
dim.height = 250;
}
}
},
);
return (
<RecyclerListView
style={styles.container}
dataProvider={dataProvider}
layoutProvider={layoutProvider}
rowRenderer={renderItem}
onEndReached={nextPage}
/>
);
};const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight || 0,
marginHorizontal: 0,
},
});
export default RecyclerList;
Then we implemented a component, RecyclerList
with RecyclerListView
. And we can render the image list with this new component. We would replace the original List
component on the Home
component later.
Actually, most of the codes are standard. What we need to do is implementing our own DataProvider
, with which the array of images are consumed, and LayoutProvider
, with which we can customize the layout. But there is still some limitation, for instance, the RecyclerListView
doesn’t support dynamic height for each element, so we are unable to render the elements with masonry list.
Update the Home component
And then the last step is to update the following line in the Home
component
import List from './List';
with
import {default as List} from './RecyclerList';
And then run the app again. But you would find nothing changed because it is just a performance enhancement to use RecyclerListView
instead of FlatList. Nothing changed for the user.
Ok. This chapter is a short and simple one. And thanks for reading it.