href
Build a URL path from one of your route patterns, with the pattern and its params checked by TypeScript.
import { GioLink, href } from '@gio.js/react';
<GioLink href={href('/posts/:id', { id: post.id })}>{post.title}</GioLink>Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
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. |
params | RouteParamsOf<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
*
* 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
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:
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
idgives/posts/- the type check does. - Before the first server start (no
.gio/routes.d.tsyet), every pattern is accepted and its params come from the pattern, so a typo in a pattern goes unnoticed. Rungio typegenin CI beforetsc. - The same registry types
useParams()and the@gio.js/coretypes such asPageProps<'/posts/:id'>andGioRequest<'/api/posts/:id'>. - Routes added by hand to
@gio.js/react'sGioRegisteredRoutesstill typehref(); declare them onGioJS.RegisteredRoutesinstead so the core types see them too.
Related
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Reads 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.6 | Introduced. |