skip to content

Images & Backgrounds

Image loads bundled assets through require, which knows their size, or remote uri sources, which need explicit dimensions, then fits them with resizeMode. Interviewers probe blank images and caching.

part ofReact Nativeoverview, primer and where to startread it →
on this pageshow

explore

questions

6

In React Native, why does an Image with a require() source appear without a size while a remote uri Image renders blank?

level: juniorimportance: must knowfreq 72%

answer

  1. one size is known at build time
  2. the bundler records width and height
  3. remote images arrive with no size
  4. no auto-size by design: no layout jumps
  5. width and height, or aspectRatio

basics

~20 s

A require() source is a bundled asset whose width and height the bundler records, so Image sizes itself on mount. A remote uri has no known size, and React Native deliberately never sizes it after download, so without dimensions it lays out at zero.

solid answer

~50 s

`require('./icon.png')` returns an opaque asset reference, a number, and the asset's metadata includes its **width and height**, so `Image` has a default size the moment it mounts. A remote source is `{uri: 'https://…'}`: nothing is known until the download finishes, and React Native **intentionally does not** resize the view afterwards, because images popping to their natural size would make the layout jump. With no `width` and `height` in the style, the image lays out with zero size and appears blank. Give remote images explicit dimensions, or a width plus an `aspectRatio` known from your API. The same applies to `data:` URIs and to images referenced by name from the native app's resources. To let a bundled image stretch with flex instead of its intrinsic size, the docs suggest `{width: undefined, height: undefined}` in its style.

code

tsx · 18 lines
tsx
import {Image, StyleSheet, View} from 'react-native';

type Props = {photoUrl: string; ratio: number};

export function ListingHero({photoUrl, ratio}: Props) {
  return (
    <View>
      {/* Remote: no size is known until download, so give it one. */}
      <Image source={{uri: photoUrl}} style={[styles.hero, {aspectRatio: ratio}]} />
      {/* Bundled: the asset carries its own width and height. */}
      <Image source={require('./icons/bed.png')} />
    </View>
  );
}

const styles = StyleSheet.create({
  hero: {width: '100%'},
});

go deeper

for a junior

Recall that bundled require() images know their size while remote uri images need explicit width and height, or they render blank.

for a middle

Explain why React Native refuses to auto-size remote images, how aspectRatio and source dimensions help, and why data: URIs and native resource names need sizes too.

for a senior

Design gallery layouts that never wait on image downloads, by getting aspect ratios from the API and reserving getSize for rare cases.

for a principal

Push for image dimensions or ratios in the content API contract so every client can lay out stably, instead of each screen measuring at runtime.

## Two kinds of source `Image` takes a `source` prop, and the two common forms behave differently at layout time. | | Bundled: `require('./bed.png')` | Remote: `{uri: 'https://…/photo.jpg'}` | |---|---|---| | What the value is | an opaque asset reference (a number) | an object with a URL | | Size known at mount | yes, recorded when the app is bundled | no, only after download | | Default layout | the asset's own width and height | zero width and height | | Needs explicit size | no (optional) | **yes** | | Density variants | `@2x`/`@3x` picked automatically | whatever the server returns | `Image.resolveAssetSource()` shows what a bundled reference resolves to: an object with `uri`, `width`, `height` and `scale`. ## Why React Native does not auto-size remote images A browser renders an unsized image as an empty box, downloads it, then resizes the box to the image's natural size, pushing everything below it down. React Native **deliberately does not implement this**. Knowing the dimensions or aspect ratio up front is more work, but the layout is stable: nothing moves when the photo arrives. The consequence is the classic bug: `<Image source={{uri}} />` with no size is laid out at **0 x 0**, the download may even succeed, and the user sees nothing. ## Sizing remote images In a real-estate listing gallery, bundled icons (bedroom, bathroom, parking) sit next to remote photos of the property. The photos need a size from somewhere: 1. **Fixed size**: `style={{width: 120, height: 90}}` for thumbnails in a grid. 2. **Width plus aspect ratio**: `style={{width: '100%', aspectRatio: 4 / 3}}` for a full-width hero, with the ratio taken from the listing API when it provides one. 3. **Measured at runtime**: `Image.getSize(url)` resolves to the image's pixel width and height, but it may download the image first, so use it sparingly, not for every thumbnail. 4. **From the source object**: the `source` may carry `width` and `height` if known in advance, which set the default dimensions of the `Image`. `resizeMode` then decides how the photo fits the box you chose. ## Sources that also need a size The explicit-size rule is not only for HTTP URLs: - **`data:` URIs** (base64 images from an API) need width and height; the docs recommend them only for very small, dynamic images. - **Images referenced by name** from the native app's resources, such as `{uri: 'app_icon'}` for an iOS asset catalog or an Android drawable, need manual dimensions and have no build-time safety check. - **Android XML drawables** need explicit dimensions too. ## When a bundled image should not use its own size Because a `require` source brings its intrinsic size, it can fight flex layout: an icon meant to fill a flexible container keeps its natural dimensions. The docs note that you may need `{width: undefined, height: undefined}` on the style to let flex size it instead. ## Debugging a blank remote image When a remote photo does not appear, check in this order: 1. **Does the `Image` have a size?** Inspect its layout; a 0 x 0 frame is the most common cause. 2. **Did the load fail?** Add `onError` and log `nativeEvent.error`: a 404, an expired signed URL or a blocked plain-HTTP request all look like an empty box. 3. **Is the frame hidden?** An `Image` inside a parent with no height, or clipped by `overflow: 'hidden'`, can load successfully and still be invisible. 4. **Is the format supported?** The docs note, for example, that `webp` on iOS is supported only when bundled with the JavaScript code. ## Other network source options The object form also accepts `method`, `headers` and `body` for the image request, useful for authenticated listing photos, and on iOS a `cache` policy. The docs strongly recommend HTTPS, which satisfies iOS App Transport Security requirements.

  • In React Native, why does Image.getSize make a poor way to size every thumbnail in a listing grid?
    `Image.getSize(url)` resolves to the image's pixel dimensions, but to learn them it may have to download the image first. Calling it for every thumbnail doubles the work before anything can be laid out, and the grid still waits on the network. Fixed thumbnail sizes, or an aspect ratio delivered by the listing API, give a stable layout without any download.
  • In React Native, how do you make a bundled require() image fill a flexible container instead of keeping its own size?
    A `require` source carries the asset's intrinsic width and height, which become the `Image`'s default size. The docs suggest setting `{width: undefined, height: undefined}` in the style so flex layout can size the image instead, then using `resizeMode` to control how it fits.

saying these in an interview costs you the question

  • A remote Image resizes itself to the photo once the download completes.
  • A remote Image renders blank because the URL must use a require() call.
  • require() returns the file path as a string.
  • Only HTTP images need explicit dimensions; data: URIs size themselves.
  • Setting resizeMode fixes a remote Image that has no width or height.
open as a page

In React Native, what do Image's resizeMode values do, which is the default, and which would you use for listing photos versus a floor plan?

level: juniorimportance: must knowfreq 58%

basics

~20 s

resizeMode sets how an Image fits a box of a different shape: cover (the default) fills and crops, contain shows everything with bands, stretch distorts, repeat tiles, center never enlarges. Listing photos suit cover; a floor plan needs contain.

open as a page

In React Native, how does Image pick between icon.png, [email protected] and [email protected], and why must the require() path be static?

level: middleimportance: should knowfreq 44%

basics

~20 s

Require the base name once; the device's screen density picks the @2x or @3x variant, falling back to the closest one. The path must be a literal string because the bundler resolves and packages assets at bundle time, not at runtime.

open as a page

In a React Native listing gallery, how do you show a placeholder while a remote Image loads and a fallback when it fails?

level: middleimportance: should knowfreq 42%

basics

~20 s

Use defaultSource for a bundled placeholder during loading, and onError to swap to a bundled fallback when the download fails. onLoadStart, onLoad and onLoadEnd track progress. On Android, defaultSource is ignored in debug builds, so test the placeholder in a release build.

open as a page

In a React Native listing gallery, how would you use Image.prefetch, Image.queryCache and Image.getSize so the next photo appears instantly at the right shape?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Prefetch the next one or two photos with Image.prefetch(url) so they are in the disk cache before the swipe, check what is already cached with Image.queryCache(urls), and use Image.getSize only when the API gives no aspect ratio, since it may download the image.

open as a page

Since React Native 0.87 deprecated ImageBackground, how do you put a price label over a listing photo, and why can't Image hold children?

level: middleimportance: nice to knowfreq 22%

basics

~20 s

Use a View sized by your layout, render an Image inside it with StyleSheet.absoluteFill, then the price label as a later sibling so it draws on top. Image cannot contain children: it throws. ImageBackground did exactly this wrapping and is deprecated since 0.87.

open as a page