Skip to content

usePathname

The usePathname hook provides access to the current pathname of the URL. It returns a string representing the current path without query parameters or hash fragments.

import { usePathname } from "@toapi/router";
function Navigation() {
const pathname = usePathname();
return (
<nav>
<a href="/" className={pathname === "/" ? "active" : ""}>
Home
</a>
<a href="/about" className={pathname === "/about" ? "active" : ""}>
About
</a>
</nav>
);
}
  • Type: string
  • Description: the current pathname without query parameters or hash fragment
  • Examples:
    • / for the root path
    • /users for a users page
    • /users/123 for a specific user
    • /products/category/electronics for nested paths

The pathname is normalized by the Router component:

  • Trailing slashes are removed: /users/ becomes /users
  • Root path remains /
import { Link, usePathname } from "@toapi/router";
function NavItem({ href, children }) {
const pathname = usePathname();
const isActive = pathname === href;
return (
<Link href={href} className={`nav-item ${isActive ? "active" : ""}`}>
{children}
</Link>
);
}
function Navigation() {
return (
<nav>
<NavItem href="/">Home</NavItem>
<NavItem href="/products">Products</NavItem>
<NavItem href="/about">About</NavItem>
<NavItem href="/contact">Contact</NavItem>
</nav>
);
}
function Layout({ children }) {
const pathname = usePathname();
const isAdminPage = pathname.startsWith("/admin");
const isPublicPage = ["/", "/about", "/contact"].includes(pathname);
return (
<div className="layout">
{!isAdminPage && <Header />}
<main className={isAdminPage ? "admin-layout" : "public-layout"}>
{children}
</main>
{isPublicPage && <Footer />}
</div>
);
}
import { Link, usePathname } from "@toapi/router";
function Breadcrumbs() {
const pathname = usePathname();
const pathSegments = pathname.split("/").filter(Boolean);
const breadcrumbs = pathSegments.map((segment, index) => {
const href = "/" + pathSegments.slice(0, index + 1).join("/");
const label = segment.charAt(0).toUpperCase() + segment.slice(1);
return { href, label };
});
return (
<nav aria-label="Breadcrumb">
<Link href="/">Home</Link>
{breadcrumbs.map((crumb, index) => (
<span key={crumb.href}>
<span> / </span>
{index === breadcrumbs.length - 1 ? (
<span aria-current="page">{crumb.label}</span>
) : (
<Link href={crumb.href}>{crumb.label}</Link>
)}
</span>
))}
</nav>
);
}
function AnalyticsProvider({ children }) {
const pathname = usePathname();
useEffect(() => {
analytics.track("Page View", {
path: pathname,
timestamp: new Date().toISOString(),
});
}, [pathname]);
return <>{children}</>;
}
  1. Use for UI state: perfect for conditional rendering and styling based on the current path.
  2. Memoize expensive computations: use useMemo for complex path-based calculations.
  3. Combine with other hooks: often used together with useParams and useSearchParams.
  4. Avoid side effects: don’t use pathname changes to trigger navigation — use useRouter instead.
// Wrong - don't navigate based on pathname changes
useEffect(() => {
if (pathname === "/old-path") {
router.push("/new-path");
}
}, [pathname]);
// Wrong - might not match due to trailing slash
const isActive = pathname === "/users/";
// Correct - router normalizes trailing slashes
const isActive = pathname === "/users";