Migration Guide: v9 → v10
Overview
In v10, the link generation process has been redesigned to give users full control over how paths are constructed.
Previously, parts of the generation logic were implicitly handled by internal implementations. In v10, this behavior is now fully customizable by the user.
As a result, some options from v9 have been removed. This guide explains how to migrate.
transform → transforms
Background
In v9, the transform option allowed users to override the final path based on the RouteContext.
const link = link_generator(route_config, {
transform: (ctx) => {
if (ctx.params) {
return "/exist-params";
}
},
});However, this approach had several issues:
- Users had to reconstruct the entire path manually
- Only a single callback was allowed
- As logic grew, the resulting path became difficult to predict
v10 Approach
In v10, users can directly mutate the RouteContext before the path is generated.
The generator will build the final path after all transforms are applied.
const link = link_generator(route_config, {
transforms: [
(ctx) => {
if (ctx.params) {
ctx.path = "/exist-params";
}
},
],
});Benefits
- No need to return a path string
- Clear separation of concerns via multiple transforms
- Predictable, step-by-step transformations
RouteContext Changes
To support more flexible manipulation:
ctx.paramsis now aMapctx.queryis now aURLSearchParams
Example Migration
Before (v9)
const route_config = {
user: { path: "/users/:id" }
} as const;
const link = link_generator(route_config, {
transform: (ctx) => {
if (ctx.id === "user") {
const uid = ctx.params?.id;
if (typeof uid !== "string") return;
const upper_uid = uid.toUpperCase();
return "/users/" + upper_uid;
}
}
});
link("user", { id: "alice" });
// => /users/ALICEAfter (v10)
const route_config = {
user: { path: "/users/:id" }
} as const;
const link = link_generator(route_config, {
transforms: [
(ctx) => {
if (ctx.id === "user") {
const uid = ctx.params.get("id"); // Use Map API!!
if (typeof uid !== "string") return;
const upper_uid = uid.toUpperCase();
ctx.params.set("id", upper_uid); // Use Map API!!
}
},
],
});
link("user", { id: "alice" });
// => /users/ALICEImportant Behavior Change
ctx.path
In v9:
ctx.pathcontained already replaced parameters
In v10:
ctx.pathcontains the raw path template
should_append_query Removal
Use format_query_fn:
const route_config = {
products: { path: "/products?size" }
} as const;
const link = link_generator(route_config, {
format_query_fn: () => ""
});
link("products", undefined, { size: "small" }); // output: /productsSummary
| Feature | v9 | v10 |
|---|---|---|
| transform | return string | mutate ctx |
| query control | should_append_query | format_query_fn |