use-url-hash
Track the URL fragment as a typed value decoded by parse.
| Package | @vizejs/composable/use-url-hash |
| Own the source | vize lib pull composable:use-url-hash |
| Runtime exports | useUrlHash |
| Gzip budget | 2560 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useUrlHash } from "@vizejs/composable/use-url-hash";
Try it
Link to a section through the hash
Read and write the URL hash so a section can be linked and restored.
What to observe: Go to install changes the page URL to #install. Use the browser's back button or edit the hash to update the output.
The default mode: "replace" updates the hash without adding history entries; use "push" to add them.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { useUrlHash } from "@vizejs/composable/use-url-hash";
const { state: section } = useUrlHash();
const sections = ["intro", "install", "usage"];
</script>
<template>
<div class="composable-example">
<p>Link to a section of the page through the URL hash.</p>
<nav class="example-actions" aria-label="Sections">
<button v-for="name in sections" :key="name" type="button" @click="() => (section = name)">
Go to {{ name }}
</button>
</nav>
<output aria-live="polite">{{
section ? `Hash: #${section}` : "No section in the URL."
}}</output>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useUrlHash |
state | experimental | deterministic-fallback | caller-managed | reactive-scope | web, desktop | window |
tryOnScopeDispose |
API
useUrlHash
Track the URL fragment as a typed value decoded by parse.
function useUrlHash<Value>(options: UseTypedUrlHashOptions<Value>): UrlHashControls<Value>
useUrlHash
Track the URL fragment as a plain string (without the leading #).
function useUrlHash(options?: UseUrlHashOptions): UrlHashControls<string>
useUrlHash
Synchronize a typed value with the URL fragment (location.hash). Reading follows hashchange and popstate. Writing state updates the fragment through history.replaceState (or pushState with mode: "push"), which neither scrolls to an anchor nor fires hashchange; an empty serialized value removes the fragment. Values are percent-decoded on read and minimally encoded on write. Server rendering: browsers never send the fragment, so without a host the value is ssrHash (when given) or the default, and no global is read. Inside a component the browser hash is first read after mounting (initialRead defaults to "post-flush" there), so hydration never mismatches. Listeners are removed with the owning reactive scope.
function useUrlHash<Value>( options: UseUrlHashOptions | UseTypedUrlHashOptions<Value> = {}, ): UrlHashControls<Value> | UrlHashControls<string>
const { state: tab } = useUrlHash({
parse: (raw) => (raw === "settings" ? "settings" : "profile"),
serialize: (value) => value,
default: "profile" as "profile" | "settings",
});
Types
UrlHashHost
Minimal window surface used by useUrlHash.
| Member | Type | Description |
|---|---|---|
location |
{ /** Fragment including the leading |
Current location; only the URL parts are read. |
history |
{ /** Current history entry state, preserved when replacing. */ readonly state: unknown; /** Replace the current entry's URL. */ readonly replaceState: (data: unknown, unused: string, url: string) => void; /** Push a new entry with the given URL. */ readonly pushState: (data: unknown, unused: string, url: string) => void; } |
Session history used to write the fragment without scrolling. |
UseUrlHashOptions
Options shared by both useUrlHash overloads.
| Member | Type | Description |
|---|---|---|
host? |
MaybeRefOrGetter<UrlHashHost | null | undefined> |
Browser host. null/undefined keeps the default (server rendering). |
mode? |
UrlHistoryMode |
History write mode for changes made through state. |
ssrHash? |
MaybeRefOrGetter<string | undefined> |
Raw hash (without #) to use while no host is attached. Browsers never send the fragment to servers, so pass it only when it is known (for example from a client-side redirect). |
initialRead? |
"sync" | "post-flush" |
When the browser hash is first read. "post-flush" keeps the server value through hydration and reads the real hash after mounting. |
UseTypedUrlHashOptions
Options for a typed useUrlHash with an explicit codec.
| Member | Type | Description |
|---|---|---|
host? |
MaybeRefOrGetter<UrlHashHost | null | undefined> |
Browser host. null/undefined keeps the default (server rendering). |
mode? |
UrlHistoryMode |
History write mode for changes made through state. |
ssrHash? |
MaybeRefOrGetter<string | undefined> |
Raw hash (without #) to use while no host is attached. Browsers never send the fragment to servers, so pass it only when it is known (for example from a client-side redirect). |
initialRead? |
"sync" | "post-flush" |
When the browser hash is first read. "post-flush" keeps the server value through hydration and reads the real hash after mounting. |
parse |
(raw: string) => Value |
Decode the raw (percent-decoded, #-less) hash. Throwing selects default. |
serialize |
(value: Value) => string |
Encode a value to a raw hash. An empty string removes the fragment. |
default |
Value |
Value used for an empty or unparsable hash. |
UrlHashControls
Reactive state and controls returned by useUrlHash.
| Member | Type | Description |
|---|---|---|
state |
Ref<Value> |
Writable hash value; assignments update the URL. |
supported |
Readonly<Ref<boolean>> |
Whether a browser host is attached. |
error |
Readonly<ShallowRef<unknown>> |
Most recent parse failure, cleared by the next successful read. |
refresh |
() => void |
Re-read the current location hash. |