react-image-size
v3.1.1
Published
React hook and utility to get image dimensions from a URL. Caching, retries, abort, SSR-safe.
Maintainers
Readme
react-image-size is a tiny, zero-dependency React library for getting the intrinsic width and height of any image from its URL. Ships with a React hook and a standalone async utility — both fully typed.
Features
- React hook —
useImageSizewithloadinganderrorstate out of the box - Standalone function —
getImageSizefor use outside of React components - Result caching — repeated calls with the same URL return instantly from cache; configure freshness with
staleTime - Request deduplication — concurrent calls for the same URL share one in-flight request
- Abort support — cancel in-flight requests via
AbortSignal - Retry support — automatically retry failed loads with exponential backoff
- Lazy loading — skip fetching until
enabled: true - Manual refetch — call
refetch()to bypass cache and re-fetch on demand - Keep previous data — hold old dimensions +
isPreviousDataflag while new URL loads - CORS support — configure
crossOriginattribute per request - Timeout support — reject slow image loads automatically
- SSR safe — no crash in server-side rendering environments
- Dual ESM / CJS — works with any bundler or module system
- Zero dependencies — no runtime deps beyond React itself
- Fully typed — written in TypeScript, types included
Installation
npm install react-image-sizeyarn add react-image-sizeQuick Start
import { useImageSize } from 'react-image-size';
function ImageInfo() {
const [dimensions, { loading, error }] = useImageSize('https://example.com/photo.jpg');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<p>
{dimensions?.width} × {dimensions?.height}
</p>
);
}Usage
useImageSize hook
The hook fetches image dimensions reactively. It re-fetches automatically when the URL or options change. Pending requests are automatically cancelled when the URL changes or the component unmounts.
import { useImageSize } from 'react-image-size';
const [dimensions, { loading, error }] = useImageSize(url, options);With timeout and retries:
const [dimensions, { loading, error }] = useImageSize(url, {
timeout: 5000,
retries: 2,
});Lazy loading — fetch only when ready:
const [dimensions, { loading, error }] = useImageSize(url, {
enabled: !!url,
});No flash on URL change with keepPreviousData:
const [dimensions, { loading, error, isPreviousData }] = useImageSize(url, {
keepPreviousData: true,
});
// dimensions holds the previous image's size while the new one loads
// isPreviousData is true while the new URL is in-flightManual refetch:
const [dimensions, { loading, refetch }] = useImageSize(url);
// Re-fetch on demand — bypasses cache
<button onClick={refetch}>Refresh</button>Stale-while-revalidate with staleTime:
const [dimensions, { loading }] = useImageSize(url, {
staleTime: 60_000, // cache is fresh for 60s; re-fetch after that
});CORS image:
const [dimensions, { loading, error }] = useImageSize(url, {
crossOrigin: 'anonymous',
});Full example:
function Avatar({ src }: { src: string }) {
const [dimensions, { loading, error }] = useImageSize(src, {
enabled: !!src,
keepPreviousData: true,
retries: 2,
timeout: 5000,
});
if (loading) return <Skeleton />;
if (error) return <Fallback />;
return (
<img
src={src}
width={dimensions?.width}
height={dimensions?.height}
alt="avatar"
/>
);
}getImageSize function
Use this outside of React (event handlers, utilities, Node.js scripts with a DOM polyfill, etc.).
import { getImageSize } from 'react-image-size';
const { width, height } = await getImageSize('https://example.com/photo.jpg');With retries:
const { width, height } = await getImageSize(url, { retries: 3, timeout: 5000 });With abort support:
import { getImageSize } from 'react-image-size';
const controller = new AbortController();
setTimeout(() => controller.abort(), 3000);
const { width, height } = await getImageSize(url, { signal: controller.signal });With error handling:
import { getImageSize, Error as ImageError } from 'react-image-size';
try {
const { width, height } = await getImageSize(url, { timeout: 5000, retries: 2 });
console.log(width, height);
} catch (err) {
if (err === ImageError.TIMEOUT) console.error('Too slow');
if (err === ImageError.ABORTED) console.error('Cancelled');
else console.error(err);
}clearCache function
Clears the entire in-memory dimensions cache.
import { clearCache } from 'react-image-size';
clearCache();clearCacheEntry function
Removes a single URL from the cache. refetch() calls this internally.
import { clearCacheEntry } from 'react-image-size';
clearCacheEntry('https://example.com/photo.jpg');API Reference
useImageSize(url, options?)
| Parameter | Type | Description |
|---|---|---|
| url | string | URL of the image to measure |
| options | UseImageSizeOptions | Optional configuration (see below) |
Returns [Dimensions | null, State]
| Value | Type | Description |
|---|---|---|
| dimensions | Dimensions \| null | { width, height } when loaded, null otherwise |
| state.loading | boolean | true while the image is being fetched |
| state.error | string \| null | Error message, or null if no error |
| state.refetch | () => void | Clears the cache entry and re-fetches |
| state.isPreviousData | boolean | true when dimensions are from the previous URL (only with keepPreviousData) |
getImageSize(url, options?)
| Parameter | Type | Description |
|---|---|---|
| url | string | URL of the image to measure |
| options | Options | Optional configuration (see below) |
Returns Promise<Dimensions> — resolves with { width, height } or rejects with an error string.
Options
| Property | Type | Default | Description |
|---|---|---|---|
| timeout | number | undefined | Max milliseconds to wait before rejecting with "Timeout" |
| signal | AbortSignal | undefined | Abort signal to cancel the request |
| retries | number | 0 | Number of retry attempts on failure (exponential backoff: 1s, 2s, 3s…) |
| crossOrigin | string | undefined | Sets img.crossOrigin — use 'anonymous' or 'use-credentials' for CORS images |
| staleTime | number | undefined | Cache TTL in milliseconds. After this, the cached result is considered stale and re-fetched |
UseImageSizeOptions
Extends Options with hook-specific fields:
| Property | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Set to false to skip fetching until ready |
| keepPreviousData | boolean | false | Keep previous dimensions while new URL is loading |
Dimensions
type Dimensions = {
width: number;
height: number;
};Error constants
Predefined rejection values you can compare against in catch blocks:
import { Error as ImageError } from 'react-image-size';
ImageError.TIMEOUT // 'Timeout'
ImageError.ABORTED // 'Aborted'
ImageError.WINDOW_IS_NOT_DEFINED // 'Window is not defined'
ImageError.URL_IS_NOT_DEFINED // 'Url is not defined'Migration Guide
v2 → v3
Error message format changed. The error string from useImageSize no longer includes the Error: prefix:
// v2
state.error === 'Error: Image not found'
// v3
state.error === 'Image not found'ESM is now the default for bundlers that resolve the exports field in package.json.
v1 → v2
// v1
import reactImageSize from 'react-image-size';
const { width, height } = await reactImageSize(url);
// v2+
import { getImageSize } from 'react-image-size';
const { width, height } = await getImageSize(url);