You tweak a prompt in Rork, regenerate the screen, and suddenly the list that was working a minute ago renders completely blank. console.log(data) says the array is populated. The FlatList is definitely on screen. Yet nothing shows up. Honestly, this is the single most common source of "wait, what?" moments I've had in React Native work.
The good news: the list of things that actually cause a blank FlatList is short. If you walk through the checks below in order, you can almost always fix it in under fifteen minutes. What follows is the exact sequence I use when debugging Rork output that produces empty lists.
Start with "is there actually room to draw?"
In my experience, around sixty to seventy percent of blank FlatList cases come down to this. Because FlatList extends ScrollView under the hood, it silently collapses to zero height when its parent hasn't reserved space. There's nothing to scroll into, so every item is rendered into a box with zero height and you see a blank screen.
Rork's AI-generated wrappers frequently forget the flex: 1 on a parent View, or accidentally nest the list inside a ScrollView. Both patterns produce the same symptom.
// ❌ Nothing will render
<View>
<FlatList
data={items}
renderItem={({ item }) => <Text>{item.title}</Text>}
keyExtractor={(item) => item.id}
/>
</View>
// ✅ Parent needs flex:1 or an explicit height
<View style={{ flex: 1 }}>
<FlatList
data={items}
renderItem={({ item }) => <Text>{item.title}</Text>}
keyExtractor={(item) => item.id}
/>
</View>If you're tempted to wrap the list in a ScrollView for a page-level scroll, don't. A FlatList inside a ScrollView breaks virtualization and hands off height calculation in a way that usually produces, yes, a blank list. Let the FlatList handle scrolling and use ListHeaderComponent / ListFooterComponent for anything that needs to sit above or below it.
Inspect the data array, including its shape
It's tempting to assume your data is fine because you logged it. But it's surprisingly common to see undefined, a wrapper object, or a promise sneaking through, especially on first render.
const { data: items, error } = await supabase.from('posts').select('*');
// ❌ items can be null on initial render
<FlatList data={items} ... />
// ✅ coerce to an array
<FlatList data={items ?? []} ... />Supabase returns an empty array (not an error) when Row Level Security rejects the query, so always check both error and items?.length together. A frequent cousin to this bug is handing the entire hook response to FlatList:
// ❌ passing the wrapper, not the array
const response = useQuery(...);
<FlatList data={response} ... />
// ✅ pluck the array out
<FlatList data={response?.data ?? []} ... />Check renderItem and keyExtractor carefully
Sometimes the list is receiving data just fine, but renderItem is rendering nothing because of a destructuring slip:
// ❌ item here is { item, index, separators }, so .title is undefined
<FlatList
data={items}
renderItem={(item) => <Text>{item.title}</Text>}
/>
// ✅ destructure
<FlatList
data={items}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>renderItem's first argument is an object — { item, index, separators }. Treating that object directly as your item is one of the easiest footguns in React Native, and it's especially easy to miss because TypeScript without strict mode won't always catch it.
keyExtractor deserves the same scrutiny. If keys are non-unique or undefined, dev builds show a warning but production builds can silently skip re-renders or stack items on top of each other.
// ❌ id is a number; returning it directly can trip type checks
keyExtractor={(item) => item.id}
// ✅ always return a string
keyExtractor={(item) => String(item.id)}Horizontal FlatLists collapse for the same reason
A vertical list works, you add horizontal, and the whole thing disappears. Same root cause: the parent's width and height aren't pinned.
// ❌ collapses with no explicit height
<FlatList
horizontal
data={items}
renderItem={({ item }) => <Card item={item} />}
/>
// ✅ wrap in a fixed-height parent
<View style={{ height: 200 }}>
<FlatList
horizontal
data={items}
renderItem={({ item }) => <Card item={item} />}
showsHorizontalScrollIndicator={false}
/>
</View>For horizontal lists, pinning a numeric height on the parent is the most reliable fix. Setting height: '100%' on the items themselves doesn't help if the parent hasn't committed to a size.
Conditionally mounting the list itself
I shipped this one to production once, so I'll admit it first. Rendering the FlatList conditionally on items.length > 0 means the list unmounts on every empty state — during loading, during filter changes, anywhere the array briefly empties. The result: flicker, no enter animation, sometimes a brief flash of blank screen that looks exactly like "the list is broken."
// ❌ FlatList unmounts whenever items is empty
{items.length > 0 && (
<FlatList data={items} ... />
)}
{items.length === 0 && <Text>No data</Text>}
// ✅ Keep FlatList mounted; handle empty via ListEmptyComponent
<FlatList
data={items}
renderItem={({ item }) => <Row item={item} />}
keyExtractor={(item) => String(item.id)}
ListEmptyComponent={
loading
? <ActivityIndicator style={{ marginTop: 40 }} />
: <Text style={{ textAlign: 'center', marginTop: 40 }}>No data</Text>
}
/>ListEmptyComponent lets you handle empty, loading, and error states inside the same mounted list, which also saves you from unnecessary remount cost.
Small tricks for isolating the problem
When none of the above pinpoints it, these four moves almost always surface the root cause fast:
- Pass a hard-coded array:
data={[{id: '1', title: 'test'}]}. If this renders, the issue is upstream in data fetching. - Render something maximally visible:
renderItem={({ item }) => <Text style={{ color: 'red', fontSize: 40 }}>X</Text>}. If red X's appear, the original renderItem's internal layout is the culprit. - Add a debug border:
style={{ borderWidth: 2, borderColor: 'red' }}. A thin horizontal line means zero height; a huge box means the layout is fine and the items are collapsing instead. - Log the actual layout:
onLayout={(e) => console.log(e.nativeEvent.layout)}. If width or height is zero, the parent is to blame.
When you ask Rork's AI to fix the screen, don't just say "the list is blank." Say something like: "FlatList receives data (length=5) but renders an empty area. The parent View may have height 0." Pairing a symptom with a hypothesis dramatically raises the quality of the regenerated code — the same principle you'd use when asking a human colleague for help.
When the list flickers but doesn't render
There's a close cousin of the blank-list bug: the list flashes briefly, then goes blank. This is almost always state-related. A common cause is calling setState with a new array reference every render — for example, filtering inside the JSX — which tells FlatList to throw away its virtualized row cache and start over. On slower Android devices, the first frame after that reset is often blank.
// ❌ filter runs on every render, returning a new array reference
<FlatList
data={items.filter((i) => i.isActive)}
renderItem={renderRow}
/>
// ✅ memoize the filtered array so the reference is stable
const activeItems = useMemo(
() => items.filter((i) => i.isActive),
[items]
);
<FlatList data={activeItems} renderItem={renderRow} />useMemo here isn't a micro-optimization — it's a correctness fix. FlatList assumes the array reference is stable between renders unless the data itself genuinely changed. Giving it a fresh reference on every render forces a full re-virtualization pass, and that's enough to look broken on mid-range phones.
What to copy into your next Rork prompt
Once you've been bitten by this once, it's worth saving a small snippet you can paste into Rork's prompt box whenever you ask it to generate a list screen. Something like:
Generate a list screen. Use FlatList, not ScrollView. Wrap it in a
<View style={{ flex: 1 }}>. ProvidekeyExtractorreturning a string. Handle empty/loading states viaListEmptyComponent, not conditional rendering. UseuseMemoif the data is filtered inline.
This one paragraph, pasted into prompts, cuts the blank-list bug rate to nearly zero in my own projects. Rork is happy to follow structural constraints when you spell them out; it just doesn't always invent them on its own.
Related reading
Blank FlatList bugs look like isolated issues, but they're often rooted in broader layout decisions. These companion pieces help you prevent the same category of issue elsewhere:
- Rork App Performance Optimization Complete Guide
- How to Fix Slow or Freezing Rork Apps
- React Native Memory Leak Fix Guide
Closing thought
Before anything else, go back to the screen that's blank and just check whether the FlatList's parent has flex: 1 or an explicit height. That single fix clears a surprising share of these cases. Once that's locked down, verifying the data shape and the renderItem destructuring makes this class of bug something you'll spot in seconds, not hours.
A final small mindset shift that helped me: treat a blank list the same way you'd treat a failed network request. It's not a mysterious rendering glitch — it's one of maybe six or seven very predictable causes. The more you internalize that small decision tree, the less intimidating AI-generated list screens become, and the more confidently you can ship them.