API.md

@lazarv/react-server/navigation

この API リファレンスはまだ翻訳されていません。以下は英語版の内容です。

Client navigation surface: <Link>, <Form>, <Refresh>, <ReactServerComponent>, hooks for location/search params/matching, navigation guards, redirect helpers, and scroll restoration.

function createRoute<TPath extends string, TParams = ExtractParams<TPath>, TSearch = Record<string, string>>(path: TPath, options?: ClientRouteOptions<TParams, TSearch>): RouteDescriptor<TPath, TParams, TSearch>; function createRoute(path: "*", options?: Omit<ClientRouteOptions, "exact">): RouteDescriptor<"*", {}, {}>; function createRoute(path: `${string}/*`, options?: Omit<ClientRouteOptions, "exact">): RouteDescriptor<string, {}, {}>; function createRoute(options?: Omit<ClientRouteOptions, "exact">): RouteDescriptor<"*", {}, {}>; function createRoute(): RouteDescriptor<"*", {}, {}>;

Client-safe route factory — returns a RouteDescriptor with path, validate, href(), .Link, .useParams(), and .useSearchParams() — but no .Route.

Use this in shared route definition files that are imported by both server components and client components.

// routes.ts (shared) import { createRoute } from "@lazarv/react-server/navigation"; import { z } from "zod"; export const user = createRoute("/user/[id]", { validate: { params: z.object({ id: z.string() }) }, }); // Client component: const params = user.useParams(); // typed! user.href({ id: "42" }); // → "/user/42" <user.Link params={{ id: "42" }}>User 42</user.Link>
function Form(props: FormProps): React.JSX.Element;

A component that renders a form element that navigates to the current route using form data as the query parameters.

Parameters

Returns — The form element

import { Form } from '@lazarv/react-server/navigation'; export default function App() { return ( <Form> <input type="text" name="name" /> <button type="submit">Submit</button> </Form> ); }
function Link<T extends string>(props: LinkProps<T>): React.JSX.Element;

A component that renders an anchor element that links to a route.

Parameters

Returns — The anchor element

import { Link } from '@lazarv/react-server/navigation'; export default function App() { return ( <Link to="/todos">Todos</Link> ); }
function ReactServerComponent(props: ReactServerComponentProps): React.JSX.Element;

A component that renders a server component. The component will be rendered on the server and hydrated on the client.

Parameters

Returns — The server component

import { ReactServerComponent } from '@lazarv/react-server/navigation'; export default function App() { return ( <ReactServerComponent url="/todos" outlet="todos" defer /> ); }
function redirect(url: string, options?: { replace?: boolean; }): never;

Perform a client-side redirect by throwing a RedirectError. Must be called during render inside a component wrapped by a Route (which automatically includes a RedirectBoundary).

The RedirectBoundary catches the error and uses the full navigation system to perform the redirect, supporting both client-only and server routes.

Parameters

"use client"; import { redirect } from '@lazarv/react-server/navigation'; export default function ProtectedPage() { if (!isAuthenticated) { redirect("/login"); } return <div>Secret content</div>; }
function Refresh(props: RefreshProps): React.JSX.Element;

A component that triggers a refresh of the current route.

Parameters

Returns — The anchor element

import { Refresh } from '@lazarv/react-server/navigation'; export default function App() { return ( <Refresh>Refresh</Refresh> ); }
function registerRouteResources(path: string, resources: (RouteResourceBinding | RouteResource)[]): () => void;

Register resource bindings for a route path on the client side.

When a client-only navigation matches the path, the registered resources are loaded in parallel before the component renders — eliminating the waterfall that would occur if the component's .use() call triggered the loader.

Call this at module level in a "use client" module (alongside your client-side resource loaders).

Parameters

Returns — Cleanup function that unregisters the bindings

"use client"; import { registerRouteResources } from "@lazarv/react-server/navigation"; import { todos } from "./resources.client"; registerRouteResources("/todos", [ todos.from((_, search) => ({ filter: search.filter ?? "all" })), ]);
function registerScrollContainer(id: string, element: HTMLElement): void;

Register a scrollable container element for automatic scroll position save/restore alongside the window scroll.

Parameters

function ScrollRestoration(props?: ScrollRestorationProps): null;

Provides automatic scroll restoration for client-side navigations.

Place this component once at the top level of your app.

"use client"; import { ScrollRestoration } from '@lazarv/react-server/navigation'; export default function App() { return ( <> <ScrollRestoration /> <nav>...</nav> <main>...</main> </> ); }
Smooth scrolling ```tsx <ScrollRestoration behavior="smooth" />
<Link name="unregister-scroll-container"> ### `unregisterScrollContainer` </Link> ```ts function unregisterScrollContainer(id: string): void;

Unregister a scrollable container previously registered with registerScrollContainer.

function useLocation(outlet?: string): Location | null;

A hook that returns the current location.

Parameters

Returns — The current location

function useMatch<T = Record<string, string>>(path: string, options?: ClientMatchOptions): T | null;

A client-side hook that matches a route path pattern against the current pathname. Returns the matched params or null if no match.

This is the isomorphic counterpart to the server-side useMatch from @lazarv/react-server/router. Works in "use client" components.

Parameters

Returns — The matched route params, or null

"use client"; import { useMatch } from '@lazarv/react-server/navigation'; export default function UserProfile() { const params = useMatch('/users/[id]'); if (!params) return null; return <p>User: {params.id}</p>; }

Returns a navigate function that accepts a URL string or a route descriptor.

Returns — A navigate function.

import { useNavigate } from '@lazarv/react-server/navigation'; const navigate = useNavigate(); navigate('/about'); navigate(products, { search: { sort: 'price' } });
function useNavigationGuard(guard: NavigationGuard, options?: NavigationGuardOptions): void;

React hook to register a navigation guard for the lifetime of the component.

The guard callback is called before every client-side navigation. Return false to block navigation, a string to redirect, or true/undefined to allow.

Use the beforeUnload option to also show the browser's native "Leave site?" dialog when the user tries to close the tab or navigate away externally.

For pattern matching, use useMatch() inside the guard handler rather than a pattern parameter — this is more composable.

Parameters

"use client"; import { useNavigationGuard } from '@lazarv/react-server/navigation'; // Leave guard with beforeunload support export default function Editor() { const [dirty, setDirty] = useState(false); useNavigationGuard( (from, to) => { if (dirty) { return confirm("You have unsaved changes. Leave?"); } }, { beforeUnload: dirty } ); return <textarea onChange={() => setDirty(true)} />; }
// Enter guard — redirect unauthenticated users useNavigationGuard((from, to) => { if (!isAuthenticated && to.startsWith("/dashboard")) { return "/login"; } });
function usePathname(outlet?: string): string | null;

A hook that returns the current pathname.

Parameters

Returns — The current pathname

function useRouteMatch<TPath extends string, TParams, TSearch>(route: RouteDescriptor<TPath, TParams, TSearch>): TParams | null;

Test if a route matches the current pathname and return typed params (or null).

Parameters

Returns — Matched params or null.

import { useRouteMatch } from "@lazarv/react-server/navigation"; import { user } from "./routes"; const match = useRouteMatch(user); if (match) console.log(match.id);
function useRouteParams<TPath extends string, TParams, TSearch>(route: RouteDescriptor<TPath, TParams, TSearch>): TParams | null;

Read typed, validated params for a route. Uses the route's validate.params schema (if provided) to parse the raw match.

Parameters

Returns — Parsed params, or null if the route doesn't match / validation fails.

import { useRouteParams } from "@lazarv/react-server/navigation"; import { user } from "./routes"; const { id } = useRouteParams(user); // id: string
function useRouteSearchParams<TPath extends string, TParams, TSearch>(route: RouteDescriptor<TPath, TParams, TSearch>): TSearch;

Read typed, validated search params for a route. Uses the route's validate.search schema (if provided) to parse query params.

Parameters

Returns — Parsed search params.

import { useRouteSearchParams } from "@lazarv/react-server/navigation"; import { products } from "./routes"; const { sort, page } = useRouteSearchParams(products);
function useScrollContainer(id: string, ref: React.RefObject<HTMLElement>): void;

Hook that registers a scrollable container element for automatic scroll position save/restore. Handles registration on mount and cleanup on unmount.

Parameters

"use client"; import { useRef } from "react"; import { useScrollContainer } from "@lazarv/react-server/navigation"; export function Sidebar() { const ref = useRef<HTMLElement>(null); useScrollContainer("sidebar", ref); return <nav ref={ref} style={{ overflow: "auto", height: "100vh" }}>...</nav>; }
function useScrollPosition(handler: (params: ScrollPositionParams) => ScrollPosition | false | undefined | null): void;

Register a per-route scroll position handler.

The handler is called on every navigation with { to, from, savedPosition }. Return { x, y } to scroll to a custom position, false to skip scrolling entirely (useful for modal routes), or undefined/null to fall back to the default behavior.

Call this hook from any client component — only the most recently registered handler is active. The handler is automatically unregistered on unmount.

"use client"; import { useScrollPosition } from "@lazarv/react-server/navigation"; export function ScrollConfig() { useScrollPosition(({ to }) => { if (to.startsWith("/modal")) return false; return undefined; // default behavior }); return null; }
function useSearchParams(outlet?: string): Record<string, string | string[]> | null;

A hook that returns the current search parameters as a plain object. Multi-value keys are returned as arrays.

Parameters

Returns — The current search parameters as { [key]: string | string[] }, or null

class RedirectBoundary extends React.Component<React.PropsWithChildren> { }

Error boundary that catches RedirectError thrown by client-side redirect(). Uses the proper navigation system to perform the redirect.

Automatically wrapped around route content by Route — you typically don't need to use this directly.

import { RedirectBoundary } from '@lazarv/react-server/navigation'; <RedirectBoundary> <ProtectedContent /> </RedirectBoundary>
class RedirectError extends Error { url: string; replace: boolean; constructor(url: string, options?: { replace?: boolean; }); }

Error class thrown by client-side redirect(). Caught by RedirectBoundary which uses the proper navigation system to perform the redirect.

interface NavigateFunction { (url: string, options?: Parameters<NavigateToUrl>[1]): Promise<void>; <TPath extends string, TParams, TSearch>(route: RouteDescriptor<TPath, TParams, TSearch>, options?: RouteNavigateOptions<TParams, TSearch>): Promise<void>; }

Navigate function returned by useNavigate().

Accepts either:

In typed mode, search is merged with the current URL search params.

const navigate = useNavigate(); // Classic — plain URL navigate("/about"); // Typed — route with search params (merged with current URL) navigate(products, { search: { sort: "price", page: 2 } }); // Typed — route with path params + search navigate(user, { params: { id: "42" }, search: { tab: "posts" } });
interface NavigationGuardOptions { beforeUnload?: boolean; }

Options for useNavigationGuard.

interface RouteNavigateOptions<TParams = {}, TSearch = {}> { params?: TParams; search?: Partial<TSearch> | ((prev: TSearch) => TSearch); outlet?: string; push?: boolean; rollback?: number; signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode; }

Options when navigating to a route descriptor

interface ScrollPosition { x: number; y: number; }

The position passed to or returned from a scroll position handler.

interface ScrollPositionParams { to: string; from: string | null; savedPosition: ScrollPosition | null; }

Parameters passed to the useScrollPosition handler callback.

interface ScrollRestorationProps { behavior?: ScrollBehavior; }
type ClientMatchOptions = { exact?: boolean; };

Options for the client-side useMatch hook.

type FormProps = Exclude<React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement> | Exclude<LinkProps<string>, "to">, "action" | "method" | "search" | "to">;

The props for the Form component.

type LinkProps<T> = React.PropsWithChildren<{ to: T; search?: Record<string, unknown> | ((prev: Record<string, string | string[]>) => Record<string, unknown>); target?: string; local?: boolean; root?: boolean; transition?: boolean; push?: boolean; replace?: boolean; prefetch?: boolean; ttl?: number; revalidate?: boolean | number | ((context: { outlet: string; url: string; timestamp: number; }) => Promise<boolean> | boolean); rollback?: number; noCache?: boolean; fallback?: React.ReactNode; Component?: React.ReactNode; onNavigate?: () => void; onError?: (error: unknown) => void; }> & React.DetailedHTMLProps<React.HTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;

The props for the Link component.

type NavigationGuard = (from: string, to: string) => NavigationGuardResult | Promise<NavigationGuardResult>;

A navigation guard callback function. Called before every client-side navigation.

Parameters

Returns — Whether to allow the navigation, block it, or redirect

type NavigationGuardResult = boolean | string | undefined;

The result type returned by a navigation guard callback.

type ReactServerComponentProps = React.PropsWithChildren<{ url?: string; outlet: string; defer?: boolean; }>;

The props for the ReactServerComponent component.

type RefreshProps = React.PropsWithChildren<{ url?: string; target?: string; local?: boolean; root?: boolean; transition?: boolean; prefetch?: boolean; ttl?: number; revalidate?: boolean | number | ((context: { outlet: string; url: string; timestamp: number; }) => Promise<boolean> | boolean); noCache?: boolean; fallback?: React.ReactNode; Component?: React.ReactNode; onRefresh?: () => void; onError?: (error: unknown) => void; }> & React.DetailedHTMLProps<React.HTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;

The props for the Refresh component.