React Native SectionList - Complete Guide with Examples

Last update: 2025-04-24
Type
Quick Win's logo Quick Win
Membership
🆓
Tech
Share:

The SectionList component in React Native is a powerful tool for displaying sectioned data in a scrollable list. In this quick win, we’ll explore how to implement and customize SectionList with practical examples and best practices.

Basic SectionList Implementation

The SectionList component requires a specific data structure where each section must have a title and a data array. Let’s start with a simple SectionList implementation that groups food items by category:

import React from 'react';
import { View, Text, SectionList, StyleSheet } from 'react-native';

const BasicSectionList = () => {
	// Each section must have a title and a data array
	// The data array contains the items for that section
	const DATA = [
		{
			title: 'Fruits',
			data: ['Apple', 'Banana', 'Orange', 'Mango']
		},
		{
			title: 'Vegetables',
			data: ['Carrot', 'Broccoli', 'Spinach']
		},
		{
			title: 'Dairy',
			data: ['Milk', 'Cheese', 'Yogurt']
		}
	];

	return (
		<SectionList
			sections={DATA} // Your sectioned data array
			keyExtractor={(item, index) => item + index} // Unique key for each item
			renderItem={({ item }) => (
				// How each list item should be rendered
				<View style={styles.item}>
					<Text style={styles.itemText}>{item}</Text>
				</View>
			)}
			renderSectionHeader={({ section: { title } }) => (
				// How each section header should be rendered
				<View style={styles.header}>
					<Text style={styles.headerText}>{title}</Text>
				</View>
			)}
		/>
	);
};

// Styles to make our list look clean and organized
const styles = StyleSheet.create({
	item: {
		padding: 15,
		backgroundColor: '#fff',
		borderBottomWidth: 1,
		borderBottomColor: '#eee'
	},
	itemText: {
		fontSize: 16
	},
	header: {
		padding: 15,
		backgroundColor: '#f4f4f4'
	},
	headerText: {
		fontSize: 18,
		fontWeight: 'bold'
	}
});

export default BasicSectionList;

The SectionList component requires several key props:

  • sections: An array of objects containing your sectioned data
  • renderItem: A function that returns the UI for each item in a section
  • renderSectionHeader: A function that returns the UI for each section header
  • keyExtractor: A function to generate unique keys for list items

Advanced Features

1. Custom Item Separators

Separators help distinguish between items and sections visually. You can customize both item separators (between items in a section) and section separators (between different sections):

const AdvancedSectionList = () => {
	// Custom separator component for items within a section
	const renderSeparator = () => <View style={styles.separator} />;

	return (
		<SectionList
			// ... other props from basic example
			ItemSeparatorComponent={renderSeparator} // Renders between items within sections
			SectionSeparatorComponent={() => (
				// Renders between sections
				<View style={styles.sectionSeparator} />
			)}
		/>
	);
};

const styles = StyleSheet.create({
	separator: {
		height: 1,
		backgroundColor: '#e0e0e0' // Light gray line between items
	},
	sectionSeparator: {
		height: 2,
		backgroundColor: '#f0f0f0' // Slightly thicker line between sections
	}
});

2. Pull to Refresh

Pull-to-refresh is a common pattern in mobile apps that allows users to update the list content by pulling down. Here’s how to implement it with proper loading states:

const RefreshableSectionList = () => {
	const [refreshing, setRefreshing] = useState(false); // Track refresh state
	const [data, setData] = useState(initialData);

	const onRefresh = async () => {
		setRefreshing(true); // Show the refresh spinner
		try {
			// Simulate or make an actual API call
			const newData = await fetchNewData();
			setData(newData); // Update the list with new data
		} catch (error) {
			console.error('Error refreshing:', error);
			// You might want to show an error message to the user here
		}
		setRefreshing(false); // Hide the refresh spinner
	};

	return (
		<SectionList
			sections={data}
			refreshing={refreshing} // Controls the refresh spinner
			onRefresh={onRefresh} // Called when the user pulls to refresh
			// ... other props
		/>
	);
};

3. Sticky Headers

Sticky headers remain visible at the top of the list while scrolling through their section, improving navigation and context:

<SectionList
	sections={DATA}
	stickySectionHeadersEnabled={true} // iOS is true by default, Android needs this prop
	// ... other props
/>

Working with Complex Data

Real-world applications often need to display more complex data structures. Here’s an example of a user list with online/offline status:

const ComplexSectionList = () => {
	// Complex data structure with nested objects
	const COMPLEX_DATA = [
		{
			title: 'Online Users',
			data: [
				{ id: 1, name: 'John Doe', status: 'active', lastSeen: 'now' },
				{ id: 2, name: 'Jane Smith', status: 'active', lastSeen: 'now' }
			]
		},
		{
			title: 'Offline Users',
			data: [
				{ id: 3, name: 'Mike Johnson', status: 'inactive', lastSeen: '2h ago' },
				{ id: 4, name: 'Sarah Wilson', status: 'inactive', lastSeen: '1d ago' }
			]
		}
	];

	// Custom render function for complex items
	const renderItem = ({ item }) => (
		<View style={styles.complexItem}>
			<Text style={styles.userName}>{item.name}</Text>
			<View style={styles.userInfo}>
				{/* Use emojis as status indicators */}
				<Text style={styles.status}>{item.status === 'active' ? '🟢' : '⚫️'}</Text>
				<Text style={styles.lastSeen}>{item.lastSeen}</Text>
			</View>
		</View>
	);

	return (
		<SectionList
			sections={COMPLEX_DATA}
			keyExtractor={(item) => item.id.toString()} // Use unique IDs for keys
			renderItem={renderItem}
			renderSectionHeader={({ section: { title } }) => (
				<View style={styles.complexHeader}>
					<Text style={styles.complexHeaderText}>{title}</Text>
				</View>
			)}
		/>
	);
};

// Enhanced styles for complex data display
const styles = StyleSheet.create({
	complexItem: {
		padding: 15,
		flexDirection: 'row', // Horizontal layout
		justifyContent: 'space-between',
		alignItems: 'center',
		backgroundColor: '#fff'
	},
	userName: {
		fontSize: 16,
		fontWeight: '500'
	},
	userInfo: {
		flexDirection: 'row',
		alignItems: 'center'
	},
	status: {
		marginRight: 8
	},
	lastSeen: {
		color: '#666',
		fontSize: 14
	},
	complexHeader: {
		padding: 15,
		backgroundColor: '#f8f8f8',
		borderBottomWidth: 1,
		borderBottomColor: '#eee'
	},
	complexHeaderText: {
		fontSize: 18,
		fontWeight: 'bold',
		color: '#333'
	}
});

Performance Optimization

Large lists can impact performance. Here’s how to optimize your SectionList for better performance:

const OptimizedSectionList = () => {
	// Memoize the render function to prevent unnecessary re-renders
	const renderItem = useCallback(
		({ item }) => (
			<View style={styles.item}>
				<Text>{item}</Text>
			</View>
		),
		[] // Empty dependency array since render doesn't depend on props/state
	);

	// Pre-calculate dimensions for fixed-height items
	// This helps SectionList optimize rendering
	const getItemLayout = (data, index) => ({
		length: 50, // Fixed height of each item
		offset: 50 * index, // Position of each item
		index
	});

	return (
		<SectionList
			sections={DATA}
			renderItem={renderItem}
			getItemLayout={getItemLayout}
			initialNumToRender={10} // Number of items to render initially
			maxToRenderPerBatch={10} // Number of items to render per batch
			windowSize={5} // Number of screens worth of content to render
			// ... other props
		/>
	);
};

Best Practices

  1. Performance

    • Use getItemLayout for fixed-height items
    • Implement useCallback for render functions
    • Optimize initialNumToRender and maxToRenderPerBatch
  2. User Experience

    • Add loading indicators
    • Implement pull-to-refresh
    • Use sticky headers when appropriate
    • Add proper error handling
  3. Data Management

    • Keep data structures consistent
    • Handle empty sections gracefully
    • Implement proper key extraction
  4. Styling

    • Use consistent styling across sections
    • Consider platform-specific designs
    • Implement proper spacing and separators

Common Use Cases

  • Contact lists with alphabetical sections
  • Settings screens with grouped options
  • Product catalogs with categories
  • Chat applications with message grouping
  • Timeline views with date-based sections

Summary

SectionList is a versatile component that helps organize and display sectioned data efficiently in React Native applications. By following these patterns and implementing the features discussed, you can create polished and performant sectioned lists.

Key takeaways:

  • Structure your data properly with sections
  • Customize headers and separators
  • Implement performance optimizations
  • Follow best practices for smooth user experience
  • Handle complex data structures effectively

Now you’re ready to implement beautiful sectioned lists in your React Native apps! 🚀

Zero to Hero React Native Mission
Simon Grimm