Lists and forms are most of what apps do. They are also where AI-generated code most often causes jank and keyboard bugs.
Core concepts
- FlatList and FlashList: Virtualised lists render only visible rows. Provide
keyExtractor, keep row components light and memoised, and consider FlashList for very long or complex lists. — FlashList - Pull to refresh and pagination: Use
refreshing/onRefreshandonEndReachedwith a page cursor, guarding against duplicate requests. — FlatList - Validated forms: Define a schema, show field-level errors, disable submit while pending and handle server errors. React Hook Form with Zod is a common pairing. — React Hook Form
- Keyboard behaviour: Use
KeyboardAvoidingViewor a keyboard-aware scroll view, dismiss on tap outside, and setreturnKeyTypeandonSubmitEditingso the keyboard flows naturally. — KeyboardAvoidingView
Concept videos
YouTube channels and searches for these topics. On a large screen they open in the reading panel next to the roadmap.
- Forms in React Native — YouTube search: React Native form validation react hook form zod
Explanation
Row components must be cheap
Heavy rows make scrolling stutter. Memoise row components and avoid creating new functions or objects inline on every render when rows are numerous.
Test with a long list
Seed 1,000 items during development so performance issues show up early.
What Is It?
Lists and forms are the two core interaction patterns of data-driven apps.
Why Should I Care?
Good defaults here prevent the most common performance and usability complaints.
Real World Analogy
A virtualised list is a conveyor belt showing only the items in front of you instead of laying every item on the floor.
Visual Mental Model
data -> FlatList (visible window) -> memoised Row
form input -> schema validation -> submit state -> server errorSmallest Possible Example
import { FlatList } from 'react-native';
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Row item={item} />}
onEndReached={loadMore}
onEndReachedThreshold={0.5}
/>;Common Mistakes
❌ Using array index as key.
Reordering causes wrong rows to update; use a stable id.
❌ No submit-pending state.
Users double-tap and create duplicates.
Build This Mini Project
Build a list of 1,000 seeded items with pull-to-refresh and pagination, plus a create form that validates and shows server errors.
Prompts for Cursor, Claude Code & Codex
Paste these into Cursor, Claude Code, Codex, or any coding agent. Replace the bracketed parts with your app details, and keep the agent in plan mode first so you review the approach before it edits files.
Optimise a slow list
This list scrolls poorly: [paste component]. Identify causes (inline functions, heavy rows, missing keys), apply fixes, and explain each. Keep behaviour identical.Validated form
Create a sign-up form with email and password using react-hook-form and zod: inline errors, disabled submit while pending, keyboard flow, and server error display. Use components/ui.Rules, databases & blogs to use
- TanStack Query rule: data fetching for lists
- Mobile rules: performance and UI rules

