------------------------- | Infinite Scroll List | ------------------------- | Item 1 | | Item 2 | | Item 3 | | ... | | Loading more... | -------------------------
Infinite scrolling (onEndReached) in React Native - Mini App: Build & Ship
import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native'; export default function InfiniteScrollList() { const [data, setData] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { // TODO: Load initial 20 items here }, []); const loadMore = () => { // TODO: Load 20 more items and update data }; const renderItem = ({ item }) => <Text style={styles.item}>{item}</Text>; return ( <View style={styles.container}> <FlatList data={data} keyExtractor={(item) => item} renderItem={renderItem} onEndReached={loadMore} onEndReachedThreshold={0.5} ListFooterComponent={loading ? <ActivityIndicator size="small" /> : null} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 50 }, item: { padding: 20, borderBottomWidth: 1, borderColor: '#ccc' }, });
import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native'; export default function InfiniteScrollList() { const [data, setData] = useState([]); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); useEffect(() => { loadMore(); }, []); const loadMore = useCallback(() => { if (loading) return; setLoading(true); setTimeout(() => { const newItems = []; const start = (page - 1) * 20 + 1; for (let i = start; i < start + 20; i++) { newItems.push(`Item ${i}`); } setData(prevData => [...prevData, ...newItems]); setPage(prevPage => prevPage + 1); setLoading(false); }, 1000); // simulate network delay }, [loading, page]); const renderItem = ({ item }) => <Text style={styles.item}>{item}</Text>; return ( <View style={styles.container}> <FlatList data={data} keyExtractor={(item) => item} renderItem={renderItem} onEndReached={loadMore} onEndReachedThreshold={0.5} ListFooterComponent={loading ? <ActivityIndicator size="small" /> : null} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 50 }, item: { padding: 20, borderBottomWidth: 1, borderColor: '#ccc' }, });
This solution uses React Native's FlatList to display a list of items. Initially, it loads 20 items labeled 'Item 1' to 'Item 20'.
The loadMore function adds 20 more items each time it is called, simulating a network delay with setTimeout. It uses a loading state to avoid multiple loads at once.
The onEndReached prop triggers loadMore when the user scrolls near the bottom. A loading spinner shows at the bottom while loading more items.
This creates a smooth infinite scrolling experience without duplicates.
------------------------- | Infinite Scroll List | ------------------------- | Item 1 | | Item 2 | | Item 3 | | ... | | Item 40 | | Loading more... | -------------------------
Practice
What is the main purpose of the onEndReached prop in a React Native FlatList?
Solution
Step 1: Understand
This prop triggers a function when the user scrolls near the end of the list.onEndReachedroleStep 2: Compare with other options
Refreshing is handled byonRefresh, initial items byinitialNumToRender, and styling is unrelated.Final Answer:
To detect when the user scrolls near the end of the list to load more items -> Option AQuick Check:
onEndReachedtriggers loading more [OK]
- Confusing onEndReached with pull-to-refresh
- Thinking it controls initial render count
- Assuming it styles the list footer
Which of the following is the correct way to use onEndReached in a FlatList?
<FlatList
data={data}
renderItem={renderItem}
onEndReached={_____}
/>Solution
Step 1: Understand event handler syntax
onEndReachedexpects a function, so we pass a function reference or an arrow function.Step 2: Analyze options
onEndReached() ("onEndReached()") calls an undefined function immediately. loadMoreItems() ("loadMoreItems()") executes immediately on render. () => loadMoreItems ("() => loadMoreItems") returns the function but does not call it when triggered. loadMoreItems ("loadMoreItems") passes the correct function reference.Final Answer:
loadMoreItems -> Option DQuick Check:
Pass a function reference, not call it immediately [OK]
- Calling the function immediately instead of passing it
- Passing undefined or wrong function name
- Confusing function reference with function call
Given this code snippet, what will happen when the user scrolls near the end of the list?
const [items, setItems] = React.useState([1, 2, 3]);
const loadMore = () => {
setItems(prev => [...prev, prev.length + 1]);
};
return (
<FlatList
data={items}
renderItem={({item}) => <Text>Item {item}</Text>}
keyExtractor={item => item.toString()}
onEndReached={loadMore}
/>
);Solution
Step 1: Understand loadMore function
It adds a new item with value one greater than current length to the items array.Step 2: Analyze onEndReached effect
When user scrolls near the end,loadMoreis called, so items grow by one each time.Final Answer:
The list will add one new item each time the end is reached -> Option AQuick Check:
onEndReached triggers loadMore which appends items [OK]
- Thinking the list resets instead of appending
- Assuming loadMore is not called automatically
- Expecting a crash without seeing infinite state updates
What is the main problem with this infinite scrolling implementation?
const [items, setItems] = React.useState([1, 2, 3]);
const loadMore = () => {
setItems(prev => [...prev, prev.length + 1]);
};
return (
<FlatList
data={items}
renderItem={({item}) => <Text>Item {item}</Text>}
keyExtractor={item => item.toString()}
onEndReached={loadMore}
onEndReachedThreshold={0.1}
/>
);Assume the list is short and the user scrolls to the bottom.
Solution
Step 1: Understand onEndReached behavior
When the list is short, scrolling near the end triggersloadMorerepeatedly because the end is always near.Step 2: Identify consequence
This causes many state updates rapidly, which can cause performance problems or infinite loops.Final Answer:
loadMore will be called repeatedly causing many state updates and possible performance issues -> Option CQuick Check:
Repeated onEndReached calls cause performance issues [OK]
- Ignoring repeated calls without loading state
- Blaming keyExtractor or renderItem incorrectly
- Thinking threshold prevents repeated calls
You want to implement infinite scrolling with a loading spinner at the bottom. Which approach correctly prevents multiple loadMore calls while loading?
const [items, setItems] = React.useState([]);
const [loading, setLoading] = React.useState(false);
const loadMore = async () => {
if (loading) return;
setLoading(true);
const newItems = await fetchMoreItems();
setItems(prev => [...prev, ...newItems]);
setLoading(false);
};
return (
<FlatList
data={items}
renderItem={({item}) => <Text>{item}</Text>}
keyExtractor={item => item.id}
onEndReached={loadMore}
ListFooterComponent={loading ? <ActivityIndicator /> : null}
/>
);What is the key reason this works well?
Solution
Step 1: Identify loading state role
Theloadingstate preventsloadMorefrom running if a load is already in progress.Step 2: Understand async loading and UI feedback
While loading, the spinner shows in the footer, and new calls are blocked until loading finishes.Final Answer:
It uses a loading state to block new calls until the current load finishes -> Option BQuick Check:
Loading state blocks repeated calls during fetch [OK]
- Not blocking repeated calls causing multiple fetches
- Calling fetchMoreItems synchronously (wrong)
- Misusing ListFooterComponent to block scrolling
Ready to prove it?
Pass the test and this pattern moves unknown
