2.0 beta — new releases can include breaking changes. Stable 1.x docs
dimah-s3v2.0.0-beta.0

useObjectUrl

Headless React hook that signs a URL for a private object, caches it, and refreshes it before it expires.

useObjectUrl signs a GET URL for one object so you can show it in an <img>, <video>, <audio>, <iframe>, or link. It asks for disposition: "inline" by default.

components/avatar-image.tsx
"use client";

import { useObjectUrl } from "@dimah-s3/react";

export function AvatarImage({ objectKey }: { objectKey: string | null }) {
  const { url, isLoading } = useObjectUrl({ route: "avatar", objectKey });

  if (isLoading) {
    return <div className="bg-muted size-16 animate-pulse rounded-full" />;
  }
  if (!url) return null;

  return (
    <img src={url} alt="Avatar" className="size-16 rounded-full object-cover" />
  );
}

For a ready-made image with loading and error states, use ObjectImage.

Keys

url is only ever the URL for the current objectKey. When the key changes, url is null and isLoading is true until the new URL is signed. A late response for the old key is ignored.

objectKey of null, undefined, or "" clears the URL. With no key, the hook needs no S3Api.

Cache and refresh

URLs are cached per S3Api, keyed by route, object key, disposition, and file name. Hooks that show the same object share one request.

expiresAt is when the URL stops working, in milliseconds since the epoch. The hook computes it in the browser from the response's expiresIn. It signs the URL again refreshBeforeMs before that time (default 60 seconds). A URL that lives less than twice refreshBeforeMs refreshes at half its lifetime instead. During a refresh, the current URL stays until the new one arrives.

Proxy URLs (download.mode: "proxy") do not expire. Their expiresAt is null and they stay until you call refresh().

refresh() drops the cached URL and signs again. If a request for the same object is already running, it joins that request.

Errors

A failed first request leaves url empty and sets error to an APIError. A failed background refresh sets error but keeps the current url while it still works. A transient failure (status 408, 429, or 500 and up) is retried with backoff until the URL expires; any other failure is not retried. Once the URL expires, url is cleared. Show the error with useFormatDimahError, and call refresh() to try again.

Type reference

import type { UseObjectUrlOptions, UseObjectUrlReturn } from "@dimah-s3/react";

UseObjectUrlOptions

Prop

Type

UseObjectUrlReturn

Prop

Type

On this page