All hooks / Browser APIs
useScript
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.
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| Parameter | Description |
|---|---|
src | Script URL. |
options | enabled 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
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| URLWidely available | 32+ | 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.