GioJSdocs
On this page

usePathname

Read the path of the current page - without query, hash or locale prefix - on the server and in the browser.

tsx
import { usePathname } from '@gio.js/react';

export function Breadcrumb() {
  const pathname = usePathname(); // '/blog/hello-world'
  return <p>You are at {pathname}</p>;
}

Reference

Parameters

usePathname takes no parameters.

Returns

A string: the path the page was rendered for, starting with /.

URLusePathname()
/'/'
/blog/hello?tab=comments#top'/blog/hello'
/fr/about (with [i18n] locales en, fr)'/about'
/docs rewritten to /help by a [[rewrites]] rule'/help'
/blog/caf%C3%A9'/blog/caf%C3%A9'

Behavior

  • The value comes from the route the server matched. The server render and the hydration render read the same value, so there is never a hydration mismatch.
  • After a soft navigation, every hydrated component reads the new page's path. After a redirect it is where the redirect landed.
  • In a not-found.tsx or error.tsx page it is the path that was requested.
  • Outside a tree GioJS rendered (a component rendered by a unit test or in a separate React root) it falls back to window.location.pathname, and '/' on the server.

Examples

app/(site)/nav.tsx
import { GioLink, usePathname } from '@gio.js/react';

export function Nav() {
  const pathname = usePathname();
  const link = (href: string, label: string) => (
    <GioLink href={href} aria-current={pathname === href ? 'page' : undefined}>
      {label}
    </GioLink>
  );
  return (
    <nav>
      {link('/', 'Home')}
      {link('/pricing', 'Pricing')}
    </nav>
  );
}

Tracking page views

The effect runs on the first render in the browser and again after every navigation to another path. sendBeacon rather than a POST fetch(): the router treats every same-origin fetch() mutation as a change and empties its prefetch cache.

app/(site)/analytics.tsx
import { useEffect } from 'react';
import { usePathname } from '@gio.js/react';

export function Analytics() {
  const pathname = usePathname();
  useEffect(() => {
    navigator.sendBeacon('/api/page-view', JSON.stringify({ path: pathname }));
  }, [pathname]);
  return null;
}

Code outside React can listen for the gio:navigated event on window instead, which the router dispatches each time it renders a page in place (links, back and forward, form answers).

Good to know

  • In the root layout it never updates. app/layout.tsx is server-only HTML that a soft navigation does not re-render, so there the value stays that of the page loaded in full. Read it in a route group's layout or a page.
  • Escapes in the path are kept as the server canonicalized it: unreserved characters are decoded, everything else stays percent-encoded (%20, %C3%A9). Decode with decodeURIComponent before showing it.
  • A trailing slash in the URL is kept (/blog/), although the router ignores it when it matches the route.
  • With [i18n], combine it with useLocale() to rebuild the prefixed URL.
  • A route.ts handler has no hook: read req.path.

Version history

VersionChanges
v0.1.0-beta.8Introduced.