Consider a situation where you want to display a list of items from an API. For example, the Coffee API’s response looks like this:
One possible way to display this to the client is to use the map
method on this array like so:
const data = getDataFromAPI(); return ( <View style={styles.container}> {data && ( <View> <Text> Your data has loaded! Here is the result:</Text> {data.map((item) => ( <Text key={item.id}> {item.name}</Text> ))} </View> )} </View> );
Here, we are using conditional rendering to check if the data has loaded. If true, we will notify the user and display the list on the screen.
This will be the output:
The code should work. So why isn’t our list visible?
This is where FlatList
comes in to mitigate this problem. It is a React Native component that allows you to render lists with zero hassle and minimal code.
Here’s what we’ll cover:
- FlatList syntax
- Sample usage
- Displaying data from an API
- FlatList customization
- FlatList navigation methods
- Best practices
- Common problems and questions
FlatList
syntax
FlatList
uses the following syntax:
import { FlatList } from "react-native"; <FlatList data={ //the array to render } keyExtractor={ // Extract keys for each item in the array } renderItem={ //each item from the array will be rendered here } />;
- In the
data
prop, you will enter the array that you want to display. This can be JSON data from an API - The
keyExtractor
prop will retrieve a unique key for each item in the array
N.B., if your array contains akey
orid
field, you don’t need to include this prop. By default,FlatList
will look for thekey
orid
property. renderItem
will tell React Native how to render the items from the list
Sample usage
Now that we’ve covered the syntax, let’s use it to render our list:
//the data array contains our array of items. const data = [{id:1, title:"Black", description:""},... ]; const Item = ({ title, description }) => ( <View> <Text style={styles.title}>{title} </Text> <Text>{description} </Text> </View> ); const renderItem = ({ item }) => ( <Item title={item.title} description={item.description} /> ); return ( <View style={styles.container}> {data && ( <FlatList data={data} renderItem={renderItem} keyExtractor={(item) => item.id} /> )} </View> );
Let’s deconstruct this code piece by piece:
- The
Item
component will accept two props:title
anddescription
. This component will display them to the UI - The
renderItem
function will render theItem
component for every item in the array. As a result, this will display thetitle
anddescription
fields from each object - Moreover, the
keyExtractor
prop tells React Native that it should use theid
field as a key - In the end, we used conditional rendering to render the data with the
FlatList
React Native element
The keyExtractor
prop
In our code sample above, notice that we used a FlatList property called keyExtractor
. This prop is useful for extracting an identifier for a given item at the specified index.
By default, keyExtractor
uses the item.key
or the item.id
key as an identifier from the array.
Here are a few examples:
const shoppingList = [ { id: 1, item: "Eggs" }, { id: 2, item: "Milk" }, { id: 3, item: "Bread" }, ]; //here, the identifier for 'shoppingList' is 'id'. By default, keyExtractor uses 'key' or 'id' properties, therefore including the keyExtractor prop is not necessary return <FlatList data={shoppingList} />; const namesList = [ { cardNumber: "1A1", name: "Hussain" }, { cardNumber: "1A2", name: "Sabrina" }, ]; //here, we need to include the keyExtractor prop. Otherwise, our code will throw an error. return <FlatList data={namesList} keyExtractor={(item) => item.cardNumber} />;
The data
prop
FlatList’s data
property is a required prop which accepts an array of items that we want to display onto the screen.
Here is a brief code sample which shows its usage in detail:
const namesList = [{cardNumber: "1A1", name:"Jules"}, {cardNumber: "1A2", name: "Rue"},{cardNumber:"1A3", name:"Fezco"}]; //our data can be a simple array: return (<FlatList data={namesList} keyExtractor={(item)=> item.cardNumber}/>) //Alternatively, we can fetch data from an API and render it like so: const [applesList, setAppleList] = useState(null) setAppleList(fetchFromAPI()); //fetch data from an API and store it into the 'applesList' Hook return (<FlatList data={applesList} keyExtractor={(item)=> item.key}/>)
The renderItem
prop
renderItem
is a callback function which is responsible for the design of our list view. This allows us to use CSS code to enhance our FlatList’s appearance.
Here is an example for renderItem
:
const data = [ { id: 1, title: "First item" }, { id: 2, title: "Second item" }, ]; const renderItem = ({ item }) => { //the app will represent each list item via a Text component return <Text style={styles.item}> {item.title}</Text>; }; <FlatList data={data} //pass in our data array renderItem={renderItem} //tell React to use our renderItem function that we defined earlier />; //use CSS to decorate our list const styles = StyleSheet.create({ item: { backgroundColor: "blue", color: "white", padding: 2, margin: 2, }, });
Displaying data from an API
In the real world, React Native developers might have to deal with rendering API data into lists.
In the code below, we are fetching data from the Coffee API and plugging it into our FlatList component:
export default function App() { const [data, setData] = useState(null); const getData = async () => { const resp = await fetch("https://api.sampleapis.com/coffee/hot"); const data = await resp.json(); setData(data); }; //on first mount, fetch data. useEffect(() => { getData(); }, []); const Item = ({ title, description, index }) => ( <View> <Text style={styles.title}> {index}. {title} </Text> <Text> {description} </Text> </View> ); const renderItem = ({ item, index }) => ( <Item description={item.description} title={item.title} index={index} /> ); return ( <View style={styles.container}> {data && ( <FlatList data={data} renderItem={renderItem} /> )} </View> ); }
A few inferences from this code:
- When the
App
component is first rendered, React invokes thegetData
method. This will make aGET
request to the API - In the
renderItem
function, we are also using theindex
argument. This is the index corresponding to the current item in the array - Notice that we aren’t using the
keyExtractor
prop. This is because anid
field is already present, soFlatList
will use this as the key
FlatList
customization
Header component
FlatList also has support for header components. This can be handy in cases where you want to display a search bar on the top of an inventory of contacts.
The ListHeaderComponent
prop can help you do that:
import { Divider } from "react-native-elements"; const header = () => { return ( <View> <Text style={styles.title}> Coffee list</Text> <Divider orientation="vertical" /> </View> ); }; return ( <View style={styles.container}> {data && ( <FlatList ListHeaderComponent={header} data={data} renderItem={renderItem} /> )} </View> );
In the above block of code, we first created a header
function and then passed it into our ListHeaderComponent
prop. This will output a simple Text
and Divider
component at the top of the FlatList
component.
Footer component
Consider a situation where the user has scrolled all the way down and wants to go back up. Here, it would be sensible to show a button that would take the client back up automatically. In this case, you could append a footer component for your list. This will indicate that the list has concluded.
You can do it via the ListFooterComponent
prop like so:
//This will be our footer component const endComponent = () => { return ( <View> <Divider orientation="vertical" /> <Text style={styles.text}> List ended</Text> </View> ); }; return ( <View style={styles.container}> {data && ( <FlatList ListFooterComponent={endComponent} data={data} renderItem={renderItem} /> )} </View> );
Separators
Separator components help the user distinguish each element in the list. This contributes to a better user experience and interface.
To achieve this, use the ItemSeparatorComponent
prop like so:
const separator = () => { return <Divider orientation="vertical" />; }; return ( <View style={styles.container}> {data && ( <FlatList ItemSeparatorComponent={separator} data={data} renderItem={renderItem} /> )} </View> );
Handling empty lists
Let’s say that you have built a note-taking app in React Native. If the user has no records, it would be suitable to show a “No notes found” message.
For this, the ListEmptyComponent
prop is useful:
const data = []; //empty array const handleEmpty = () => { return <Text style={styles.title}> No data present!</Text>; }; return ( <View style={styles.container}> {!data && <Text> Loading</Text>} {data && ( <FlatList ListEmptyComponent={handleEmpty} data={data} renderItem={renderItem} /> )} </View> );
FlatList
navigation methods
FlatList
also includes a few utility functions for scroll-related operations.
Scroll to end
Assume that you have a list containing hundreds of items. Here, it would be good to display a button that lets the user go all the way down. This will result in a better user experience since the user doesn’t have to manually scroll to the bottom, thus saving time.
To make this possible, you can use the scrollToEnd
method like so:
const list = useRef(null); const press = () => { list.current.scrollToEnd({ animated: true }); }; const header = () => { return <Button onPress={() => press()} title="Go to end" />; }; return ( <View style={styles.container}> {!data && <Text> Loading</Text>} {data && ( <FlatList ref={list} ListHeaderComponent={header} data={data} renderItem={renderItem} /> )} </View> );
In this piece of code, we created a useRef
Hook which will grant us access to FlatList
’s utility functions. When the user clicks on the Button
element, the app will execute the scrollToEnd
method.
Navigating to a specific index item
We can even scroll to a specific item by calling the scrollToIndex
method like so:
const list = useRef(null); const press = () => { //scroll to the 12th item in the index. list.current.scrollToIndex({ animated: true, index: 12 }); }; const header = () => { return <Button onPress={() => press()} title="Go to 12th index" />; }; return ( <View style={styles.container}> {!data && <Text> Loading</Text>} {data && ( <FlatList ref={list} ListHeaderComponent={header} data={data} renderItem={renderItem} /> )} </View> );
In this code snippet, we told React that if the user clicks on the button, then it should redirect the user to the twelfth item in the array.
Best practices
Avoid anonymous functions
Try to avoid using anonymous functions in your FlatList
. The React Native team suggests this so that the function won’t recreate itself every time your list is displayed. This saves memory and CPU resources:
//correct way: no anonymous functions const renderItem = ({ item, index }) => ( <Text> {index}. {item.title} </Text> ); { data && ( <FlatList data={data} keyExtractor={(item) => item.id} renderItem={renderItem} /> ); } //the wrong way. Steer clear from this: { data && ( <FlatList data={data} keyExtractor={(item) => item.id} renderItem={({ item, index }) => ( <Text> {index}.{item.title} </Text> )} /> ); }
Lighter components
The heavier your components are, the more memory they take. Display as little information as you can on your list item. As a bonus, this makes your UI look cleaner.
Even if you do have items that need to display a lot of text, you can use React Navigation. If the user taps on any item, React will direct them to a separate page that will show the remaining details. Here is an example:
Common problems and questions
Images do not render
To solve this problem, check if you are loading images from the local storage or from the network (an API). React Native’s Image
module has a slightly different syntax for each use case.
The code sample below renders images from the file system:
const apiData = [ { id: 1, title: "The Simpsons", year: 1989, image: require("./simpson.jpg"), }, { id: 2, title: "SpongeBob SquarePants ", year: 1999, image: require("./spongebob.jpg"), }, ]; const renderItem = ({ item, index }) => ( <View> <Text style={styles.title}>{item.title} </Text> <Text> {item.year}</Text> <Image style={{ height: 300, width: 300}} source={item.image} resizeMode="contain" /> </View> ); return ( <View style={styles.container}> <FlatList data={apiData} keyExtractor={(item) => item.id.toString()} renderItem={renderItem} /> </View> );
Notice that we are using the require
method. This tells React Native to fetch images from the local file system.
To display images from the network, use the uri
property for your prop
like so:
const apiData = [ { id: 1, title: "The Simpsons", year: 1989, //url for image image: "https://m.media-amazon.com/images/M/MV5BYjFkMTlkYWU[email protected]@._V1_SY1000_CR0,0,666,1000_AL_.jpg", }, { id: 2, title: "SpongeBob SquarePants ", year: 1999, image: "https://nick.mtvnimages.com/uri/mgid:arc:content:nick.com:9cd2df6e-63c7-43da-8bde-8d77af9169c7?quality=0.7", }, ]; const renderItem = ({ item, index }) => ( <View> <Text style={styles.title}>{item.title} </Text> <Text> {item.year}</Text> <Image style={{ height: 300, width: 300 }} source={{ uri: item.image }} //using uri property resizeMode="contain" /> </View> ); return ( <View style={styles.container}> <FlatList data={apiData} keyExtractor={(item) => item.id.toString()} renderItem={renderItem} /> </View> );
Inverting the list
To reverse the item order, simply use the inverted
prop:
return ( <View style={styles.container}> <FlatList data={apiData} keyExtractor={(item) => item.id} renderItem={renderItem} inverted //reverses the list /> </View> );
The list should re-render when a variable changes
To solve this issue, use the extraData
prop. This will tell FlatList
to render whenever the chosen variable updates:
var changedData = 0; //other logic-related code.. return ( <View style={styles.container}> <FlatList data={apiData} extraData={changedData} keyExtractor={(item) => item.id} renderItem={renderItem} /> </View> );
This will now tell React Native to listen for changes in the changedData
variable. When a change is detected, React will re-render the list.
Performance issues when rendering a large number of items
You can use the maxToRenderPerBatch
prop. This specifies the number of items rendered per batch, which is the next group of items displayed on every scroll:
return ( <FlatList data={data} extraData={changedData} keyExtractor={(item) => item.id} renderItem={renderItem} maxToRenderPerBatch={5} //render only 5 items per scroll. )
Why not use a ScrollView
instead?
The ScrollView
component renders all the items in one go. This might be fine for small lists, but not for lists with hundreds of items.
For example, take a note-taking app. If your app renders the components and views them all at once, this will result in increased memory usage.
The FlatList
module handles things differently. It will only render items when they are about to appear and deletes them when they are off view. This results in lower memory usage.
In short, FlatList
uses lazy loading, which is better for optimization purposes.
Conclusion
In this article, we covered React Native’s FlatList
usage, its useful functions and customization options. It is a crucial component if you want to render lists in your React Native app. It is an absolute breeze to use and is rock solid.
Thank you for reading! Happy coding.
LogRocket: Instantly recreate issues in your React Native apps.

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Hi, thanks for the infomation. 👍
One question: should I also avoid anonymous functions for “keyExtractor”?
Anonymous functions for the ‘keyExtractor’ prop are alright. This is because they don’t get re-rendered repeatedly, so there’s no performance costs
Certainly everything but a deep dive.. you just showed an example of usage. As for FlatList, the most buggy component in all React Native, I highly recommend you not to talk about FlatList as a “rock solid” component. I was excepting a deep dive into the component itself and how to avoid at least the rendering issues, the images not loading within the FlatList items etc.. just a very beginner’s guide, which is great for beginners, but change the title, it’s totally misleading.
Hi Vahradrim, thank you for taking the time to read my post! I didn’t research properly and that’s my fault.
I’ve now updated my article and would like to know your thoughts.
Hi, what if the array that im showing is extracted from firebase and I don’t know what is the key value pair of the object, how do we use FlatList as the above examples it is known the keys of each key-value pair?
Hi Frank,
Check if the items in your FireStore DB contain an ‘id’ and a ‘key’ pair. You only need those to render data.
For more info, here is a simple tutorial of FlatList with Firebase:
https://rnfirebase.io/firestore/usage-with-flatlists
Hey, thanks for the article. Here is another interesting issue with flat list.
I have a View, containing flatlist inside a react-navigation tab bar.
Everything works fine, but when I add a button before flatlist, like this
..
..
the last element in the flatlist seems to be hidden behind the tab bar.
Trying to figure out what is wrong.
So would be interesting to read about best practises, like don’t use other elements except flatlist on a screen etc.