How to Make Header of FlatList Sticky in React Native
If your react native app shows a good amount of data to the user then most probably, you would be using the FlatList component. FlatList is an enhanced component to render data in lists. In this blog post, I am writing about how to make the header component of FlatList sticky.
First of all, how to add a header to your FlatList? Adding a header component is easy by making use of FlatList prop ListHeaderComponent. For example, look at the following snippet.
header= () => {
return(
<View style={styles.headerStyle}>
<Text style={styles.titleStyle}>POSTS</Text>
</View>);
}
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
ListHeaderComponent={header}
renderItem={({item}) => <Text>{item.title}</Text>}
/>
</View>
);
I hope you get it. ListHeaderComponent accepts a React component class or rendered element or a render function. But the problem with this header component is- it’s not sticky. The header would disappear when we begin to scroll down through the FlatList.
So, how to make the header component of the FlatList sticky in react native?
By using stickyHeaderIndices prop. It is the prop of the ScrollView component which can be used by the FlatList too. The prop stickyHeaderIndices accepts an array of indices of the children which needed to be sticky.
In the case of FlatList, the header component has a child index of 0. Hence using stickyHeaderIndices={[0]} make the header of your FlatList sticky.
Following is a complete react native example that shows the sticky header in FlatList.
Following is the typescript code for FlatList sticky header.
import React, {useState, useEffect} from 'react';
import {View, Text, StyleSheet, FlatList} from 'react-native';
interface Data {
id: number;
title: string;
body: string;
}
const App = () => {
const [data, setData] = useState<Data[]>([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => setData(json));
}, []);
const header = () => {
return (
<View style={styles.headerStyle}>
<Text style={styles.titleStyle}>POSTS</Text>
</View>
);
};
return (
<View style={styles.container}>
<FlatList
keyExtractor={item => item.id.toString()}
data={data}
ListHeaderComponent={header}
stickyHeaderIndices={[0]}
renderItem={({item}) => <Text>{item.title}</Text>}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
buttonView: {
flexDirection: 'row',
},
headerStyle: {
flex: 1,
height: 40,
width: '100%',
backgroundColor: 'blue',
justifyContent: 'center',
alignItems: 'center',
},
titleStyle: {
color: 'white',
},
});
export default App;
Following is the code for non typescript users.
import React, {useState, useEffect} from 'react';
import {View, Text, StyleSheet, FlatList} from 'react-native';
const App = () => {
const [data, setData] = useState('');
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => setData(json));
}, []);
const header = () => {
return (
<View style={styles.headerStyle}>
<Text style={styles.titleStyle}>POSTS</Text>
</View>
);
};
return (
<View style={styles.container}>
<FlatList
keyExtractor={item => item.id.toString()}
data={data}
ListHeaderComponent={header}
stickyHeaderIndices={[0]}
renderItem={({item}) => <Text>{item.title}</Text>}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
buttonView: {
flexDirection: 'row',
},
headerStyle: {
flex: 1,
height: 40,
width: '100%',
backgroundColor: 'blue',
justifyContent: 'center',
alignItems: 'center',
},
titleStyle: {
color: 'white',
},
});
export default App;
The output of the react-native example is as given below:
That’s how you add a sticky FlatList header in react native.
Thanks, very useful. I could not find this in the documentation.