Skip to content

Route

The Route component conditionally renders its children based on the current pathname. It supports path parameters, exact matching, and nested routing.

import { Router, Route } from "@toapi/router";
function App() {
return (
<Router>
<Route path="/users">
<UsersPage />
</Route>
<Route path="/users/:id">
<UserDetailPage />
</Route>
</Router>
);
}
  • Type: string
  • Description: the path pattern to match against the current pathname
  • Default: "" (matches any path when used as a nested route)

Path patterns support:

  • Static segments: /users, /about
  • Parameters: /users/:id, /posts/:slug
  • Wildcard paths: /files/*, /docs/*path
  • Nested paths: resolved relative to parent route context
// Static path
<Route path="/about">
<AboutPage />
</Route>
// Path with parameter
<Route path="/users/:id">
<UserPage />
</Route>
// Nested relative path (resolves to parent path + "settings")
<Route path="/users/:id">
<Route path="settings">
<UserSettings />
</Route>
</Route>
  • Type: boolean
  • Description: whether the path must match exactly (no additional segments allowed)
  • Default: false
// Matches "/users" and "/users/123" and "/users/123/posts"
<Route path="/users">
<UsersLayout />
</Route>
// Matches only "/users" exactly
<Route exact path="/users">
<UsersList />
</Route>
  • Type: ReactNode
  • Description: the content to render when the route matches

By default, a non-exact route matches its path and any deeper path:

<Route path="/about">About Page</Route> // Matches: /about, /about/anything
<Route path="/users/create">Create User</Route> // Matches: /users/create, /users/create/...

Parameters are defined with colon syntax and capture a single URL segment:

<Route path="/users/:id">
{/* Access via useParams() hook */}
</Route>
<Route path="/posts/:year/:month/:slug">
{/* Multiple parameters */}
</Route>
<Route path="/files/*">
{/* Wildcard - matches any trailing path */}
</Route>
<Route path="/docs/*path">
{/* Named wildcard - accessible via useParams() */}
</Route>

Routes can be nested to create hierarchical routing structures:

<Route path="/users">
<UsersLayout />
<Route path=":id">
<UserProfile />
<Route path="settings">
<UserSettings />
</Route>
<Route path="posts">
<UserPosts />
</Route>
</Route>
</Route>

Nested route paths are resolved relative to their parent:

<Route path="/api/v1"> {/* Full path: /api/v1 */}
<Route path="users"> {/* Full path: /api/v1/users */}
<Route path=":id"> {/* Full path: /api/v1/users/:id */}
<Route path="posts"> {/* Full path: /api/v1/users/:id/posts */}

Child routes can use absolute paths (starting with /) to ignore parent context:

<Route path="/groups/:groupId">
<Route path="/groups/admin/settings"> {/* Absolute path - matches only if groupId === "admin" */}
<AdminSettings />
</Route>
</Route>

Each Route component provides context to its children:

  • path: the full resolved path pattern
  • params: object containing captured path parameters
  • matchedPathname: the portion of the pathname that was matched

Access the parameters using the useParams() hook:

<Route path="/users/:id/posts/:postId">
<PostDetail />
</Route>
function PostDetail() {
const params = useParams(); // { id: "123", postId: "456" }
return <div>User {params.id}, Post {params.postId}</div>;
}
<Router>
<Route path="/users/:id">
<UserProfile />
</Route>
<Route path="/posts/:slug">
<BlogPost />
</Route>
<Route path="/categories/:category/posts/:id">
<CategoryPost />
</Route>
</Router>
<Router>
<Route path="/dashboard">
<DashboardLayout>
<Route exact path="">
<DashboardHome />
</Route>
<Route path="analytics">
<Analytics />
</Route>
<Route path="settings">
<Settings />
</Route>
</DashboardLayout>
</Route>
</Router>

Routes without a path prop match any path within their parent context:

<Route path="/users/:id">
<UserLayout />
<Route>
{/* Always renders when parent matches */}
<UserNavigation />
</Route>
<Route path="profile">
<UserProfile />
</Route>
</Route>

Wildcard routes match arbitrary paths including slashes:

// Unnamed wildcard - matches but doesn't capture
<Route path="/static/*">
<StaticFileHandler />
</Route>
// Named wildcard - captures matched path in params
<Route path="/files/*path">
<FileViewer />
</Route>
function FileViewer() {
const params = useParams();
// params.path = "documents/report.pdf" for /files/documents/report.pdf
return <div>Viewing: {params.path}</div>;
}
// Combining parameters with wildcards
<Route path="/api/:version/*rest">
<APIProxy />
</Route>
function APIProxy() {
const params = useParams();
// For /api/v1/users/123/posts
// params.version = "v1"
// params.rest = "users/123/posts"
}
  1. Use exact matching for leaf routes that shouldn’t match child paths.
  2. Keep route hierarchies shallow when possible for better performance.
  3. Use descriptive parameter names: :userId instead of :id for clarity.
  4. Group related routes under common parent routes.
  5. Use layout routes for shared UI components.
  • Router — root router component
  • Link — navigate between routes
  • Switch — render only the first matching route
  • useParams — access route parameters
  • usePathname — access the current pathname