Navigation
λ Router provides hooks for programmatic navigation, history traversal, and URL search parameter management. These hooks wrap the browser’s native Navigation API methods.
Programmatic Navigation
Section titled “Programmatic Navigation”useNavigate
Section titled “useNavigate”The useNavigate hook returns a function for navigating to a URL programmatically:
import { useNavigate } from "@studiolambda/router/react";
function LoginButton() { const navigate = useNavigate();
async function handleLogin() { await performLogin(); navigate("/dashboard"); }
return <button onClick={handleLogin}>Log in</button>;}The navigate function accepts an optional second argument with Navigation API options:
// Replace the current history entry instead of pushing.navigate("/dashboard", { history: "replace" });
// Pass state to the destination.navigate("/checkout", { state: { cartId: "abc123" } });The return value is a NavigationResult from the Navigation API, which contains committed and finished promises you can await:
const result = navigate("/next-page");
await result.committed; // URL bar has updated.await result.finished; // Navigation fully complete (transitions done).useNavigation
Section titled “useNavigation”The useNavigation hook returns the raw Navigation object from the Navigation API. Use this for advanced scenarios not covered by higher-level hooks:
import { useNavigation } from "@studiolambda/router/react";
function DebugInfo() { const navigation = useNavigation(); const entries = navigation.entries();
return <pre>{JSON.stringify(entries.map((e) => e.url))}</pre>;}History Traversal
Section titled “History Traversal”useBack
Section titled “useBack”Navigate backward in the history stack:
import { useBack } from "@studiolambda/router/react";
function BackButton() { const { back, canGoBack } = useBack();
return ( <button onClick={() => back()} disabled={!canGoBack}> Back </button> );}The canGoBack boolean reflects whether there is a previous history entry to navigate to. The back() function accepts optional Navigation API options.
useForward
Section titled “useForward”Navigate forward in the history stack:
import { useForward } from "@studiolambda/router/react";
function ForwardButton() { const { forward, canGoForward } = useForward();
return ( <button onClick={() => forward()} disabled={!canGoForward}> Forward </button> );}URL Management
Section titled “URL Management”usePathname
Section titled “usePathname”Returns the current URL pathname:
import { usePathname } from "@studiolambda/router/react";
function Breadcrumbs() { const pathname = usePathname(); const segments = pathname.split("/").filter(Boolean);
return ( <nav> {segments.map((segment, i) => ( <span key={i}> {i > 0 && " / "} {segment} </span> ))} </nav> );}useParams
Section titled “useParams”Returns the dynamic route parameters extracted from the matched URL pattern:
import { useParams } from "@studiolambda/router/react";
function UserProfile() { const { id } = useParams();
return <h1>User #{id}</h1>;}The returned object maps parameter names (from :name or *name segments) to their captured string values.
useSearchParams
Section titled “useSearchParams”Returns the current search parameters and a setter function for updating them:
import { useSearchParams } from "@studiolambda/router/react";
function FilteredList() { const [searchParams, setSearchParams] = useSearchParams(); const sort = searchParams.get("sort") ?? "newest";
function changeSort(newSort: string) { setSearchParams({ sort: newSort }); }
return ( <div> <select value={sort} onChange={(e) => changeSort(e.target.value)}> <option value="newest">Newest</option> <option value="oldest">Oldest</option> <option value="popular">Popular</option> </select> </div> );}The setter accepts multiple formats:
// Object form — replaces all params.setSearchParams({ sort: "newest", page: "2" });
// URLSearchParams instance.setSearchParams(new URLSearchParams("sort=newest&page=2"));
// Updater function — receives current params.setSearchParams((current) => { current.set("page", String(Number(current.get("page") ?? "1") + 1)); return current;});By default, setSearchParams uses history: "replace" to avoid polluting the history stack with every parameter change. You can override this:
setSearchParams({ page: "2" }, { history: "push" });Navigation State
Section titled “Navigation State”useIsPending
Section titled “useIsPending”Returns true while a navigation transition is in progress. Use this for loading indicators:
import { useIsPending } from "@studiolambda/router/react";
function NavBar() { const isPending = useIsPending();
return ( <nav className={isPending ? "nav loading" : "nav"}> {isPending && <ProgressBar />} {/* links */} </nav> );}useNavigationType
Section titled “useNavigationType”Returns the type of the most recent navigation:
import { useNavigationType } from "@studiolambda/router/react";
function PageTransition({ children }) { const type = useNavigationType(); // type: "push" | "replace" | "reload" | "traverse" | null
const animation = type === "traverse" ? "slide" : type === "push" ? "fade" : "none";
return <div className={`transition-${animation}`}>{children}</div>;}useNavigationSignal
Section titled “useNavigationSignal”Returns the AbortSignal from the current navigation event. The signal aborts when the navigation is cancelled (e.g., by a new navigation starting). Pass this to fetch() calls to automatically cancel stale requests:
import { useNavigationSignal } from "@studiolambda/router/react";
function DataPage() { const signal = useNavigationSignal();
useEffect(() => { fetch("/api/data", { signal }) .then((res) => res.json()) .then(setData) .catch((err) => { if (err.name !== "AbortError") throw err; }); }, [signal]);
return <div>{/* ... */}</div>;}Returns null before any navigation has occurred.