skip to content

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.