GioJSdocs
On this page

href

Build a URL path from one of your route patterns, with the pattern and its params checked by TypeScript.

tsx
import { GioLink, href } from '@gio.js/react';

<GioLink href={href('/posts/:id', { id: post.id })}>{post.title}</GioLink>

Reference

ParameterTypeDefaultDescription
pattern (required)RoutePattern-A route pattern of your app, as the router writes it: /about, /posts/:id, /docs/*slug (catch-all), /shop/*path? (optional catch-all). Route groups never appear in patterns.
paramsRouteParamsOf<pattern>-The values of the pattern's params. Not accepted for a static route, optional when every param is optional, required otherwise.

Returns

The path as a string. Each param value is URL-encoded with encodeURIComponent; a catch-all value is encoded segment by segment, so its / separators stay. An empty or missing optional catch-all drops its segment entirely (/shop, not /shop/), and an empty result is /.

Types

At every server start (and with gio typegen), GioJS writes .gio/routes.d.ts, which fills the global GioJS.RegisteredRoutes interface with every page and route.ts pattern and its params. With that file in your tsconfig include (the starters have it), a pattern that is not one of your routes, or a missing or misspelled param, fails tsc, and editors autocomplete both. Without it, any pattern is accepted and its params are read from the pattern itself: href('/posts/:id', { id }) still requires id. Only a pattern held in a plain string variable takes any params, as Record<string, string>.

.gio/routes.d.ts
/**
 * .gio/routes.d.ts
 *
 * Generated by GioJS from the discovered route patterns.
 * Do not edit - regenerated on every server start.
 */
/// <reference path="./css-modules.d.ts" />
declare global {
  namespace GioJS {
    interface RegisteredRoutes {
      '/': Record<string, never>;
      '/posts/:id': { id: string };
      '/docs/*slug': { slug: string };
      '/shop/*path?': { path?: string };
    }
  }
}
export {};

Examples

Every kind of pattern

ts
href('/about');                          // '/about'
href('/posts/:id', { id: '42' });         // '/posts/42'
href('/posts/:id', { id: 'a b/c' });      // '/posts/a%20b%2Fc'
href('/docs/*slug', { slug: 'guides/setup' });   // '/docs/guides/setup'
href('/shop/*path?');                     // '/shop'
href('/shop/*path?', { path: 'shoes/red' });     // '/shop/shoes/red'

With a query string

href builds the path only. Append a query yourself:

ts
const url = `${href('/posts/:id', { id })}?${new URLSearchParams({ tab: 'comments' })}`;
router.push(url);

Good to know

  • It runs anywhere - server, browser, tests - and has no side effects. It does not check at runtime that the route exists or that params are complete - a missing id gives /posts/ - the type check does.
  • Before the first server start (no .gio/routes.d.ts yet), every pattern is accepted and its params come from the pattern, so a typo in a pattern goes unnoticed. Run gio typegen in CI before tsc.
  • The same registry types useParams() and the @gio.js/core types such as PageProps<'/posts/:id'> and GioRequest<'/api/posts/:id'>.
  • Routes added by hand to @gio.js/react's GioRegisteredRoutes still type href(); declare them on GioJS.RegisteredRoutes instead so the core types see them too.

Version history

VersionChanges
v0.1.0-beta.8Reads the global GioJS.RegisteredRoutes registry; optional catch-alls (*slug?) drop their segment when empty. Before .gio/routes.d.ts exists, params are read from the pattern (a pattern with params used to fail with Expected 1 arguments, but got 2). RoutePattern type.
v0.1.0-beta.6Introduced.