Master React Native Vertical and Horizontal Scrolling Lists
Last update: 2025-04-24Scrolling lists are a fundamental part of most mobile applications. React Native provides several components for implementing both vertical and horizontal scrolling. In this guide, you’ll learn how to use these components effectively with practical examples.
ScrollView vs FlatList
React Native offers two main components for creating scrollable content:
- ScrollView: Best for a small number of items that are all rendered at once
- FlatList: Optimized for long lists with lazy loading and better performance
Let’s explore both approaches.
Basic ScrollView Implementation
ScrollView is perfect for simple scrolling needs:
import React from 'react';
import { View, ScrollView, Text, StyleSheet } from 'react-native';
const ScrollViewExample = () => {
return (
<View style={styles.container}>
<ScrollView style={styles.scrollView}>
{[1, 2, 3, 4, 5].map((item) => (
<View key={item} style={styles.item}>
<Text style={styles.text}>Item {item}</Text>
</View>
))}
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1
},
scrollView: {
marginHorizontal: 20
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
borderRadius: 8
},
text: {
fontSize: 16
}
});
export default ScrollViewExample;
This example demonstrates:
- Basic vertical scrolling with ScrollView
- Simple styling for container and items
- Manual rendering of list items
Horizontal ScrollView
For horizontal scrolling, just add the horizontal
prop:
import React from 'react';
import { View, ScrollView, Text, StyleSheet, Dimensions } from 'react-native';
const HorizontalScrollViewExample = () => {
return (
<View style={styles.container}>
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.scrollView}>
{[1, 2, 3, 4, 5].map((item) => (
<View key={item} style={styles.card}>
<Text style={styles.cardText}>Card {item}</Text>
</View>
))}
</ScrollView>
</View>
);
};
const { width } = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
flex: 1
},
scrollView: {
paddingVertical: 20
},
card: {
width: width * 0.8,
height: 200,
backgroundColor: '#4a90e2',
marginHorizontal: 10,
borderRadius: 12,
justifyContent: 'center',
alignItems: 'center'
},
cardText: {
color: 'white',
fontSize: 24,
fontWeight: 'bold'
}
});
export default HorizontalScrollViewExample;
Key features demonstrated:
- Horizontal scrolling enabled with
horizontal
prop - Card-style layout with dynamic width
- Hidden scroll indicator for cleaner UI
- Proper spacing between cards
FlatList for Better Performance
For longer lists, FlatList is the recommended choice:
import React from 'react';
import { View, FlatList, Text, StyleSheet } from 'react-native';
interface Item {
id: string;
title: string;
}
const DATA: Item[] = Array.from({ length: 50 }, (_, i) => ({
id: i.toString(),
title: `Item ${i + 1}`
}));
const FlatListExample = () => {
const renderItem = ({ item }: { item: Item }) => (
<View style={styles.item}>
<Text style={styles.title}>{item.title}</Text>
</View>
);
return (
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
ItemSeparatorComponent={() => <View style={styles.separator} />}
ListHeaderComponent={() => <Text style={styles.header}>My List</Text>}
ListFooterComponent={() => <Text style={styles.footer}>End of List</Text>}
onEndReached={() => {
console.log('Reached end of list');
// Load more data here
}}
onEndReachedThreshold={0.5}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1
},
item: {
backgroundColor: '#ffffff',
padding: 20,
borderRadius: 8,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5
},
title: {
fontSize: 16
},
separator: {
height: 16
},
header: {
fontSize: 24,
fontWeight: 'bold',
padding: 16
},
footer: {
padding: 16,
textAlign: 'center',
color: '#666'
}
});
export default FlatListExample;
This FlatList example showcases:
- Type-safe data with TypeScript interface
- Custom item rendering
- Separator component between items
- Header and footer components
- Infinite scrolling setup with
onEndReached
- Elegant styling with shadows
Horizontal FlatList with Cards
Here’s how to create a horizontal scrolling list with FlatList:
import React from 'react';
import { View, FlatList, Text, StyleSheet, Dimensions, Image } from 'react-native';
interface Card {
id: string;
title: string;
image: string;
}
const CARDS: Card[] = [
{
id: '1',
title: 'Nature',
image: 'https://picsum.photos/300/200?random=1'
},
{
id: '2',
title: 'City',
image: 'https://picsum.photos/300/200?random=2'
},
{
id: '3',
title: 'Technology',
image: 'https://picsum.photos/300/200?random=3'
}
// Add more cards as needed
];
const HorizontalFlatListExample = () => {
const renderCard = ({ item }: { item: Card }) => (
<View style={styles.card}>
<Image source={{ uri: item.image }} style={styles.cardImage} />
<Text style={styles.cardTitle}>{item.title}</Text>
</View>
);
return (
<View style={styles.container}>
<FlatList
data={CARDS}
renderItem={renderCard}
keyExtractor={(item) => item.id}
horizontal
showsHorizontalScrollIndicator={false}
snapToAlignment="center"
snapToInterval={width * 0.8 + 20}
decelerationRate="fast"
contentContainerStyle={styles.contentContainer}
/>
</View>
);
};
const { width } = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
flex: 1
},
contentContainer: {
paddingHorizontal: 10,
paddingVertical: 20
},
card: {
width: width * 0.8,
marginHorizontal: 10,
borderRadius: 12,
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
overflow: 'hidden'
},
cardImage: {
width: '100%',
height: 200
},
cardTitle: {
fontSize: 18,
fontWeight: 'bold',
padding: 16
}
});
export default HorizontalFlatListExample;
This example demonstrates:
- Horizontal scrolling with FlatList
- Snap-to-item behavior
- Card layout with images
- Smooth scrolling optimization
- Proper touch feedback
Performance Optimization Tips
Use FlatList for Long Lists
- Implements virtualization
- Only renders visible items
- Better memory management
Optimize Rendering
const renderItem = React.useCallback(({ item }) => <Item item={item} />, []);
Implement getItemLayout
const getItemLayout = (data, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index });
Adjust Window Size
<FlatList windowSize={5} maxToRenderPerBatch={5} initialNumToRender={10} />
Pull to Refresh
Add refresh functionality to your lists:
const [refreshing, setRefreshing] = React.useState(false);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
// Fetch new data here
setTimeout(() => {
setRefreshing(false);
}, 2000);
}, []);
<FlatList
refreshing={refreshing}
onRefresh={onRefresh}
// ... other props
/>;
Best Practices
Choose the Right Component
- Use ScrollView for small lists (less than 20 items)
- Use FlatList for longer lists
- Consider SectionList for grouped data
Performance
- Implement proper key extraction
- Optimize render methods
- Use pagination for large datasets
User Experience
- Add loading indicators
- Implement pull-to-refresh
- Show empty state components
- Handle errors gracefully
Styling
- Maintain consistent spacing
- Consider platform differences
- Implement proper touch feedback
- Use shadows and borders wisely
Common Use Cases
- Social media feeds
- Product catalogs
- Image galleries
- Chat messages
- Settings menus
Summary
React Native’s scrolling components provide powerful tools for creating smooth, performant lists. By choosing the right component and following best practices, you can create beautiful scrolling experiences in your apps.
Key takeaways:
- Use ScrollView for simple, short lists
- Choose FlatList for better performance with long lists
- Implement proper optimization techniques
- Follow platform-specific design guidelines
- Consider user experience in your implementation
Now you’re ready to implement beautiful scrolling lists in your React Native apps! 🚀