FastImage Features You Don’t Use (But Should)
You installed @d11/react-native-fast-image, swapped out <Image> for <FastImage>, and called it a day. Performance improved, scrolling got…
FastImage Features You Don’t Use (But Should)
You installed @d11/react-native-fast-image, swapped out <Image> for <FastImage>, and called it a day. Performance improved, scrolling got smoother, and the job felt done.
But here’s the thing — most developers stop at the drop-in replacement. FastImage ships with a handful of genuinely powerful features that rarely make it into codebases, and the gap shows at scale.
Here are the ones worth knowing.

1. You’re Ignoring Cache Control Modes
FastImage exposes three distinct cache strategies via the cache prop. Most developers never touch it, which means they're silently getting the default behavior — which may or may not be what their content actually needs.
<FastImage
source={{
uri: "https://example.com/banner.jpg",
cache: FastImage.cacheControl.immutable, // 👈 default if omitted
}}
style={{ width: 300, height: 200 }}
/>
Here’s what each mode actually does:
**immutable** — Downloads the image once, stores it, and never touches the network again for that URL. Perfect for content that genuinely never changes: user avatars keyed to an ID, product images with versioned URLs, static assets. If you're pointing at a URL that won't change, this is what you want.
**web** — Behaves like a browser. It respects the Cache-Control headers your server sends and revalidates when content might be stale. Use this for banners, promotions, or anything that updates on a schedule. If your backend team is already managing cache headers properly, this mode leverages all that work for free.
**cacheOnly** — Renders only from local cache and refuses to make a network request. Sounds limiting, but it's a sharp tool for specific patterns: preloaded screens, offline-first flows, or anywhere you've explicitly downloaded assets ahead of time and want guaranteed instant rendering.
The mistake most apps make is using immutable (the default) for content that does change, then wondering why users are seeing stale images. Match the cache mode to the content's actual update frequency.
2. You’re Not Setting Image Priority
When a screen loads and triggers five or ten image requests simultaneously, they all compete equally for network bandwidth. FastImage lets you influence that queue — and most apps leave this lever untouched.
// Profile photo — load this first
<FastImage
source={{
uri: user.avatarUrl,
priority: FastImage.priority.high,
}}
style={styles.avatar}
/>
// Feed thumbnails below the fold - these can wait
<FastImage
source={{
uri: item.thumbnailUrl,
priority: FastImage.priority.low,
}}
style={styles.thumbnail}
/>
Three levels: low, normal, high.
The practical application is straightforward: anything that’s immediately visible and identity-critical — profile photos, hero images, above-the-fold content — gets high. Background images, thumbnails further down a list, decorative imagery? low or normal.
In a FlatList with dozens of items, this alone can make a meaningful difference in perceived load time. The images users actually notice render first; the rest fill in naturally.
3. You’re Not Preloading
This is the most underused feature by a wide margin.
FastImage.preload() downloads images in the background before they're needed. No component, no render, no visible loading state. By the time the user navigates to a screen, the images are already sitting in cache.
// On the previous screen, before navigation
FastImage.preload([
{ uri: "https://example.com/product-detail-hero.jpg" },
{ uri: "https://example.com/user-avatar-large.jpg" },
{ uri: "https://example.com/next-screen-banner.jpg" },
]);
Where this pays off most:
- Profile screens — preload the avatar when a user taps on a name in a list
- Product detail pages — preload the hero image when a card becomes visible
- Onboarding flows — preload step 2 assets while the user is reading step 1
- Chat threads — preload profile images when a conversation is opened
The UX impact is disproportionate to the implementation effort. A screen that appeared to “load instantly” often just preloaded its assets 300ms earlier.
One important caveat: don’t preload entire datasets. Preloading 50 images at once creates memory pressure and can hurt overall app performance more than it helps. Limit it to what the user is likely to see next — a few images, not a pageful.
4. You’re Not Clearing Cache on Logout
This one isn’t about performance. It’s about correctness — and it’s a security consideration that gets skipped surprisingly often.
If your app shows user-specific content (profile photos, private images, personalized assets), those images are sitting on disk in FastImage’s cache after the user logs out. The next person who opens the app on the same device can potentially see them.
const handleLogout = async () => {
await FastImage.clearMemoryCache();
await FastImage.clearDiskCache();
// Then proceed with your normal logout flow
await auth.signOut();
navigation.replace("Login");
};
Both caches need to be cleared. Memory cache is ephemeral (gone when the app closes), but disk cache persists across sessions — which is exactly where the exposure lives.
This matters most for apps in shared-device environments: family apps, enterprise tools, healthcare, anything where a device might be handed off between users. Make cache clearing part of your logout sequence, not an afterthought.
5. You’re Using FastImage for Local Assets
FastImage’s caching pipeline is built for network images. When you use it for local bundled assets, you’re routing those images through an unnecessary native layer with no meaningful benefit.
// ❌ Wasteful — local assets don't need cache management
<FastImage source={require('./icons/close.png')} style={styles.icon} />
// ✅ Just use the built-in component
<Image source={require('./icons/close.png')} style={styles.icon} />
The built-in Image component handles local assets natively and efficiently. Reserve FastImage for remote URLs where caching, priority, and preloading actually apply. Mixing it in for static icons or bundled graphics adds overhead with no upside.
Putting It Together
A pattern that combines several of these features — priority, preloading, and appropriate cache modes — ends up looking something like this for a typical feed-to-detail flow:
// In your FeedItem component
const FeedItem = ({ item, onPress }) => {
const handlePress = () => {
// Preload detail images before navigating
FastImage.preload([{ uri: item.detailImageUrl }]);
onPress(item);
};
return (
<TouchableOpacity onPress={handlePress}>
<FastImage
source={{
uri: item.thumbnailUrl,
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable,
}}
style={styles.thumbnail}
/>
</TouchableOpacity>
);
};
// In your DetailScreen
<FastImage
source={{
uri: route.params.detailImageUrl,
priority: FastImage.priority.high,
cache: FastImage.cacheControl.web, // Respects server freshness headers
}}
style={styles.hero}
/>
FastImage earns its place in a codebase when you use it intentionally. The drop-in swap helps. The cache modes, priority hints, preloading strategy, and lifecycle hygiene are what separate a good implementation from a great one.
Most of this is a few lines of configuration. The returns are worth it.
Brought to you by Sanyam Mujavadia from the Silversky Technology crew. Curious what else we’re building? Explore more at silverskytechnology.com.
메타데이터
- post_id
- e0c92c1112d4
- slug
- fastimage-features-you-dont-use-but-should-e0c92c1112d4
- url
- https://medium.com/@silverskytechnology/fastimage-features-you-dont-use-but-should-e0c92c1112d4
- canonical_url
- https://medium.com/@silverskytechnology/fastimage-features-you-dont-use-but-should-e0c92c1112d4
- author_url
- https://medium.com/@silverskytechnology
- status
- ok
- fetched_at
- 2026-06-26 03:39:16