Routing
Wasp uses React Router under the hood. Route paths support all the standard patterns described below.
Dynamic Segments
Use :paramName in a route path to match any value in that segment. Access the matched value in your page component with the useParams hook from react-router.
route PhotoRoute { path: "/photo/:photoId", to: PhotoPage }
page PhotoPage {
component: import { PhotoPage } from "@src/PhotoPage"
}
- JavaScript
- TypeScript
import { useParams } from "react-router";
export function PhotoPage() {
const { photoId } = useParams();
return <div>Viewing photo {photoId}</div>;
}
import { useParams } from "react-router";
export function PhotoPage() {
const { photoId } = useParams<"photoId">();
return <div>Viewing photo {photoId}</div>;
}
Read more in the React Router docs on dynamic segments.
Optional Segments
Append ? to a path segment to make it optional. The route will match whether or not the segment is present.
route PhotoRoute { path: "/photo/:photoId/edit?", to: PhotoPage }
page PhotoPage {
component: import { PhotoPage } from "@src/PhotoPage"
}
- JavaScript
- TypeScript
import { useParams, useLocation } from "react-router";
export function PhotoPage() {
const { photoId } = useParams();
const { pathname } = useLocation();
const isEditing = pathname.endsWith("/edit");
return (
<div>
{isEditing ? "Editing" : "Viewing"} photo {photoId}
</div>
);
}
import { useParams, useLocation } from "react-router";
export function PhotoPage() {
const { photoId } = useParams<"photoId">();
const { pathname } = useLocation();
const isEditing = pathname.endsWith("/edit");
return (
<div>
{isEditing ? "Editing" : "Viewing"} photo {photoId}
</div>
);
}
Read more in the React Router docs on optional segments.
Splats
Use /* at the end of a route path to match any remaining path segments. Access the matched portion with the '*' param.
route FilesRoute { path: "/files/*", to: FilesPage }
page FilesPage {
component: import { FilesPage } from "@src/FilesPage"
}
- JavaScript
- TypeScript
import { useParams } from "react-router";
export function FilesPage() {
const { "*": filePath } = useParams();
// Visiting /files/docs/report.txt → filePath = "docs/report.txt"
return <div>File: {filePath}</div>;
}
import { useParams } from "react-router";
export function FilesPage() {
const { "*": filePath } = useParams();
// Visiting /files/docs/report.txt → filePath = "docs/report.txt"
return <div>File: {filePath}</div>;
}
Read more in the React Router docs on splats.
Lazy-Loaded Routes
By default, Wasp lazy-loads all page routes using React Router's lazy property. This means each page's code is only downloaded when the user navigates to it, resulting in smaller initial bundle sizes. This is especially useful for apps with many routes.
If you need a specific route to be eagerly loaded (included in the main bundle), you can set lazy: false on the route declaration:
// This route's page will be included in the initial bundle
route DashboardRoute { path: "/dashboard", to: DashboardPage, lazy: false }
Most apps won't need to change this. Disabling lazy loading is useful when you want to avoid the brief loading delay for a page that users navigate to very frequently, at the cost of a larger initial download.