◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SONNET 4.5 — Retires on the Claude API on 11/30, 27 days left. If your app calls it, check the migration target●SDK 58 — Moves to React Native 0.88. R8 is now on by default in Android release builds, and iOS prebuild generates a SceneDelegate●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SONNET 4.5 — Retires on the Claude API on 11/30, 27 days left. If your app calls it, check the migration target●SDK 58 — Moves to React Native 0.88. R8 is now on by default in Android release builds, and iOS prebuild generates a SceneDelegate●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Dev Tools
⬡ Dev Tools/2026-06-19Intermediate

When Rork-Built Lists Stutter: Designing Image Caching and Prefetch

A FlatList from Rork starts stuttering once the images pile up. Here is how I restore smoothness with expo-image caching, recyclingKey, prefetch, and a move to FlashList, with the device numbers I measured.

Rork611React Native242expo-image7FlatList10Performance25

✦ Premium Article

When I first ran an image gallery built with Rork on a real device, the first few cells scrolled smoothly, but the stutter grew more obvious the longer I kept scrolling. The Simulator never showed it; it only surfaced on a slightly older phone in my hand.

The cause was easy to guess. Each cell was re-fetching its image from the network and decoding it again every time it appeared. The FlatList Rork generates is clean and readable, but it does not design for the load that arrives once the image count grows.

As an indie developer who has built image-heavy screens like wallpaper apps many times for the App Store, I want to record here the full path from the list Rork emitted to smooth scrolling again, with the numbers I measured on device.

Why scrolling stutters

The real nature of stutter is usually a fight over the main thread. The screen redraws 60 times a second (120 on some devices), and when a large image decode cuts in between those frames, one frame misses its deadline and the view jumps.

The first job is to isolate the cause. I suspect things in this order. First, is the image re-fetched from the network every time. Second, even with a cache, is the in-memory decoded image being reused. Third, is an unnecessary re-render happening when the cell is recycled. Clear those three in order and most stutter settles.

What freshly generated code tends to do

Rork's output often looks like this.

import { FlatList, Image } from "react-native";
 
export function Gallery({ items }) {
  return (
    <FlatList
      data={items}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <Image source={{ uri: item.url }} style={{ width: 180, height: 180 }} />
      )}
    />
  );
}

This works, but the built-in Image has weak cache control and tends to decode again every time a cell is recycled. Past a few dozen images it surfaces as scroll hitching. On my own device, this implementation made memory usage climb in steps throughout the scroll, and on the older phone the screen started responding a beat late.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A step-by-step way to isolate FlatList stutter from the angle of image decoding and memory
✦Concrete expo-image cache settings plus recyclingKey to stop repeated decoding
✦A prefetch design that loads ahead of the visible range, and the line at which to move to FlashList
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ Dev Tools2026-05-02
When Your FlatList Starts Stuttering: Migrating Rork Apps to FlashList v2
When your Rork app's long lists start feeling sluggish, migrating to FlashList v2 makes scrolling dramatically smoother. Here is the practical migration path, taking advantage of v2's removal of estimatedItemSize.
⬡ Dev Tools2026-08-10
Switching to Signed URLs Killed My Image Cache — Decoupling expo-image Keys from the URL
Signed URLs rewrite their query string on every expiry, so a URL-keyed cache never hits. Here is how to pin the key with source.cacheKey, what the cache read and write APIs actually return, and what changed when I re-ran the measurements.
⬡ Dev Tools2026-07-24
Collapsing Duplicate Requests Into One: A Reference-Counted Single-Flight Layer
When several components fire the same API call at launch, you get a burst of identical requests. Here is a single-flight layer that shares one in-flight promise instead: how to build the key that decides the folding, the trap of handing out a failed promise forever, the trap of one caller's abort cancelling everyone, and the test that keeps it all from regressing, with the real network numbers alongside.