The ScrollView component in React Native is a container that allows scrolling of content that exceeds the screen size. Unlike FlatList, ScrollView renders all content at once, which is optimal for small amounts of data, forms, and screens with a known height. According to the React Native Docs, 2024, ScrollView supports vertical and horizontal scrolling, the onScroll event, programmatic position control, and zoom gestures. The component renders into the native UIScrollView on iOS and ScrollView on Android.
Key Takeaways
ScrollView is a React Native component that wraps its content in a scrollable container. If the content exceeds the screen boundaries, the user can scroll through it vertically or horizontally. ScrollView renders all child elements at mount time, regardless of whether they are visible on screen or not.
Unlike FlatList, which renders only visible elements (lazy rendering), ScrollView creates all native views immediately. This makes ScrollView convenient for forms, settings pages, product cards on a single screen — anywhere where the number of child elements is small (up to 20-30) or their exact quantity is unknown in advance.
According to the React Native Using ScrollView, 2024, ScrollView supports nested scrolling (e.g., ScrollView inside ScrollView), a bounce effect at the edge, scroll indicators, snap positioning, and gesture handling. On iOS, ScrollView automatically adds SafeArea padding through contentInsetAdjustmentBehavior.
ScrollView provides a rich set of props for controlling scroll behavior, appearance, and interactivity. Let's look at the key groups: scroll control, visual settings, events, and platform-specific features.
horizontal — switches the scroll direction from vertical (default) to horizontal. scrollEnabled — disables scrolling when needed. showsVerticalScrollIndicator and showsHorizontalScrollIndicator control the display of scroll indicators. bounces (iOS) enables/disables the bounce effect when reaching the edge of the content.
The main event is onScroll, which fires on every scroll and passes an object with nativeEvent containing contentOffset (current position), contentSize (content size), layoutMeasurement (visible area size). onMomentumScrollEnd fires after inertial scrolling completes. onScrollEndDrag — when the user lifts their finger from the screen. These events are used for implementing infinite scrolling, parallax effects, and lazy loading.
ScrollView provides methods for programmatic control via ref: scrollTo({x, y, animated}) scrolls to the specified coordinates, scrollToEnd({animated}) — scrolls to the end of content, flashScrollIndicators() — temporarily shows the scroll indicators.
const scrollRef = useRef(null);
// Scroll to top
scrollRef.current.scrollTo({ x: 0, y: 0, animated: true });
// Scroll to end
scrollRef.current.scrollToEnd({ animated: true });
Programmatic scroll control is often used in chats (auto-scroll to the latest message), forms (scroll to a field with an error), and carousels (programmatic swiping).
Choosing between ScrollView and FlatList is one of the key architectural decisions in React Native. Both components provide scrolling, but they use fundamentally different rendering strategies. ScrollView renders everything at once, FlatList — only visible elements.
| Characteristic | ScrollView | FlatList |
|---|---|---|
| Rendering | All elements at once | Only visible + buffer |
| Performance | Degrades with 30+ elements | Stable at any quantity |
| Content | Any components (forms, cards) | Uniform elements from array |
| Data size | Small to medium (up to 30 elements) | Large and unlimited |
| Horizontal scroll | Yes (horizontal prop) | Yes (horizontal) |
| Sections | No (renders as-is) | SectionList for sections |
Selection rule: ScrollView — for screens where the number of child elements is known and does not exceed 20-30 (user profile, settings form, product page). FlatList — for lists with potentially many elements (news feed, product catalog, chat messages). If the content is heterogeneous (header, form, card, footer) — ScrollView is preferable since FlatList expects uniform elements.
ScrollView supports horizontal scrolling via the horizontal prop, making it ideal for carousels, image galleries, tabs, and horizontal lists. When combined with the pagingEnabled prop (iOS) or snapToInterval, ScrollView becomes a component for page-based navigation.
The horizontal property switches the scroll direction. pagingEnabled (iOS) enables page-based scrolling, where scrolling stops only at element boundaries. snapToInterval sets the snap step in pixels for both platforms.
const ImageCarousel = ({ images }) => (
<ScrollView
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={handlePageChange}
>
{images.map((img, index) => (
<Image
key={index}
source={{ uri: img }}
style={{ width: SCREEN_WIDTH, height: 250 }}
/>
))}
</ScrollView>
);
In this carousel, pagingEnabled automatically snaps scrolling to each image boundary. onMomentumScrollEnd allows updating the current page indicator. Such a carousel runs natively and supports inertial scrolling.
For non-standard snap steps, use snapToInterval (step size in pixels) and snapToAlignment (start, center, end). Using snapToOffsets you can specify an array of specific positions for snapping. This is useful for horizontal lists with cards of different sizes.
Let's look at two typical scenarios: a form screen (vertical scroll) and a horizontal category list. Both use ScrollView with different props for optimal behavior.
A profile editing page contains heterogeneous elements: avatar, several input fields, switches, and a save button. ScrollView allows scrolling the entire page as a whole, rather than each block separately.
const ProfileScreen = () => (
<ScrollView
contentContainerStyle={styles.container}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<AvatarPicker />
<TextInput placeholder="Name" />
<TextInput placeholder="Email" />
<TextInput placeholder="About me" multiline />
<SwitchRow label="Notifications" />
<Button title="Save" />
</ScrollView>
);
The keyboardShouldPersistTaps: 'handled' prop allows scrolling and interacting with the form when the keyboard is open. contentContainerStyle applies padding to all content. This pattern is used in all form screens in React Native.
For navigating categories (chats, filters, tabs), a horizontal ScrollView with chips is used. Such a component is commonly found in marketplace and social media applications.
const CategoryChips = ({ categories, selected, onSelect }) => (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.chipContainer}
>
{categories.map((cat) => (
<Chip
key={cat.id}
label={cat.name}
isSelected={selected === cat.id}
onPress={() => onSelect(cat.id)}
/>
))}
</ScrollView>
);
A horizontal ScrollView with the indicator disabled is the standard for category strips. Each chip is a separate component with a selection state. The showsHorizontalScrollIndicator: false prop removes the scroll bar, which matches mobile app user expectations.
Frequently Asked Questions
ScrollView is suitable for small amounts of data (up to 20-30 elements) and heterogeneous content (forms, profiles, settings screens). Choose FlatList for long uniform lists — news feed, product catalog, messages.
Use the onScroll event with onScrollEndDrag or onMomentumScrollEnd. The current vertical position is in nativeEvent.contentOffset.y. For performance, use ScrollEventThrottle (iOS) to adjust the onScroll call frequency.
ScrollView renders all elements at mount, creating native views for each. With 50+ elements on screen, the memory and JS thread load grows, causing frame drops. For such cases, use FlatList with lazy rendering.
Set bounces={false}. This prop only works on iOS and disables the springy effect when reaching the edge of ScrollView. On Android, there is no bounce effect by default, so the prop is ignored.
ScrollView does not natively support infinite scrolling. However, you can combine onScroll with proximity checking to the bottom edge (contentOffset.y + screen height >= contentSize.height) and add elements to state. For serious volumes, use FlatList with onEndReached.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also