All hooks / Browser APIs

useScript

437 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

Loads an external script once and reports its status: 'idle', 'loading', 'ready', or 'error'.

Every component using the same src shares one <script> tag and one status. The tag is added on mount (never on the server) and is not removed on unmount, because a script that has run cannot be unloaded. Status is 'idle' on the server, during hydration, and while disabled.

Import

import { useScript } from '@vincent.ri/react-tils'
// or only this hook
import { useScript } from '@vincent.ri/react-tils/useScript'

Usage

const status = useScript('https://js.stripe.com/v3/', { attributes: { nonce } })
if (status === 'error') return <p>Payments are unavailable right now.</p>
if (status !== 'ready') return <Spinner />
return <Checkout stripe={window.Stripe(publishableKey)} />

Live demo

Loads a script once, on demand.

idle

When to use it

A third-party SDK has no npm package or must load from its own domain, e.g. Stripe.js, Google Maps, or a chat widget.

When not to

An npm package exists; import it, and use import() to load it lazily. In Next.js, next/script also handles loading strategies. A failed load stays 'error' for that src; to retry, change the src.

API

function useScript(src: string, options?: ScriptOptions): ScriptStatus
ParameterDescription
srcScript URL.
optionsenabled and attributes. Optional.

Types

export type ScriptStatus = "idle" | "loading" | "ready" | "error";
export type ScriptOptions = {
  /** Load only while `true`, e.g. after consent or when a feature opens. Default `true`. */
  enabled?: boolean;
  /** Extra attributes for the `<script>` tag, e.g. `{ nonce, crossorigin: 'anonymous' }`. Applied when it is created. */
  attributes?: Record<string, string>;
};

Browser support

UsesChromeEdgeFirefoxSafariChrome AndroidSafari iOS
URLWidely available32+12+19+7+32+7+

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).

Coming from another library?

Other libraries call this useExternal.