React Native Sticky Date like whatsapp using Inverted SectionList
If you are currently developing a chat application and you have a requirement to stick a date while scrolling messages to let user know current date of messages user is viewing right now. This post is for you!
Inverted SectionList
If you create a SectionList with inverted false header stick properly while you scroll up and down
But when you use set inverted={true} SectionList its behaviour change you have to implement “renderSectionFooter” instead of “renderSectionHeader”
For example lets create a small app using following code
import React, { Component } from 'react';import { SafeAreaView, StyleSheet, View, Text, SectionList } from 'react-native';const DATA = [{title: '4th April, 2020',data: [ 'Message No. 0',
................ 'Message No. 19', ],},{title: '3rd April, 2020',data: [ 'Message No. 0',
................ 'Message No. 19', ],},{title: '2nd April, 2020',data: [ 'Message No. 0',
................ 'Message No. 19', ],},{title: '1st April, 2020',data: [ 'Message No. 0',
................ 'Message No. 19', ],},];const Item = ({ title }) => ( <View style={styles.item}> <Text style={styles.title}>{title}</Text> </View>);class App extends Component {render() { return ( <> <SafeAreaView style={styles.container}> {this.renderStickyDate()} <SectionList sections={DATA} inverted={true} keyExtractor={(item, index) => item + index} renderItem={({ item }) => <Item title={item} />} renderSectionFooter={({ section: { title } }) => ( <View style={styles.stickyDate}> <Text style={styles.stickyDateText}>{title}</Text> </View> )} /> </SafeAreaView> </> ); }}
add simple style
const styles = StyleSheet.create({container: { flex: 1, marginHorizontal: 16,},item: { backgroundColor: '#f9c2ff', padding: 20, marginVertical: 8,},header: { fontSize: 24, backgroundColor: '#fff', alignSelf: 'center',},title: { fontSize: 24,},stickyDate: { alignSelf: 'center', textAlign: 'center', justifyContent: 'center', backgroundColor: '#f9c2ff', borderRadius: 10, marginBottom: 10,},stickyDateText: { color: '#000', padding: 5,},});
Result will be like this
You can see header is not stick; so if we need to implement sticky date like other chat apps we have to write some custom code
Luckily react-native’s SectionList provide us a property named onViewableItemsChanged. Read more
Now make following changes into your code
Add state currentDate
state = { currentDate: null,};
add a method to update currentDate value in state
updateStickyDate = ({ viewableItems, changed }) => { if (viewableItems && viewableItems.length) { const lastItem = viewableItems.pop(); if (lastItem && lastItem.section) { this.setState({ currentDate: lastItem.section.title, }); } }};
add render date method to show date of viewable items/messages
renderStickyDate = () => { const { currentDate } = this.state; return currentDate ? ( <View style={styles.stickyDate}> <Text style={styles.stickyDateText}>{currentDate}</Text> </View> ) : null;};
add onViewableItemsChanged prop in SectionList
<SectionList .....
onViewableItemsChanged={this.updateStickyDate}
/>
Final Code will be like this
Thanks for reading this long post;