Pull-to-refresh gesture works smoothly (if implemented)
Why it matters
When a feed of dynamic data has no RefreshControl, users have no way to force fresh content — they back out of the screen and re-enter just to trigger a fetch, or they assume the app is broken. A stuck refreshing={true} that never resets is worse: the spinner burns indefinitely, users wait, then force-quit. Both patterns inflate perceived load time and trigger abandonment before the real content loads.
Severity rationale
Low because the app still functions, but the friction drives repeat navigation and degrades perceived freshness.
Remediation
Add RefreshControl to every FlatList or ScrollView rendering dynamic data, and reset the refreshing flag in a finally block so network errors do not strand the spinner:
const [refreshing, setRefreshing] = useState(false);
const onRefresh = async () => {
setRefreshing(true);
try { await fetchData(); } finally { setRefreshing(false); }
};
<FlatList refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />} />
Detection
-
ID:
pull-to-refresh -
Severity:
low -
What to look for: Count all scrollable lists that display dynamic data (FlatList, SectionList, ScrollView with fetched content). For each, check whether
RefreshControlis configured with anonRefreshhandler andrefreshingstate. -
Pass criteria: At least 100% of scrollable lists with dynamic data have
RefreshControlconfigured with bothrefreshingstate andonRefreshhandler. Pull-to-refresh provides clear visual feedback (spinner, progress) and completes the refresh action without UI freeze. Report the ratio: "X of Y scrollable lists have RefreshControl." -
Fail criteria: Any scrollable list with dynamic data is missing
RefreshControl, or it exists but has janky animations or therefreshingstate is never reset (spins indefinitely). -
Skip (N/A) when: The app has no scrollable lists with dynamic data — all content is static or the app has no list views.
-
Detail on fail:
"Pull-to-refresh missing from main feed — users cannot refresh without leaving and returning to the screen."or"RefreshControl exists but spins indefinitely after release." -
Remediation: Add RefreshControl to ScrollView or FlatList with clear feedback:
const [refreshing, setRefreshing] = useState(false); const onRefresh = async () => { setRefreshing(true); await fetchData(); setRefreshing(false); }; <FlatList data={items} refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />} renderItem={({ item }) => <ItemRow item={item} />} />
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-ux-patterns·automated