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 { Route } from "@farbenmeer/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
<Route path="/about">About Page</Route> // Matches: /about, /about/
<Route path="/users/create">Create User</Route> // Matches: /users/create, /users/create/

Parameters are defined with square brackets and capture URL segments:

<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 to ignore parent context:

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

Each Route component provides context to its children:

  • path: The full resolved path pattern
  • params: Object containing captured path parameters

Access this context 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="/">
<HomePage />
</Route>
<Route path="/about">
<AboutPage />
</Route>
<Route path="/contact">
<ContactPage />
</Route>
</Router>
<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>
<Router>
<Route path="/admin">
<AdminLayout>
<Route path="users">
<UsersSection>
<Route exact path="">
<UsersList />
</Route>
<Route path=":id">
<UserDetail>
<Route exact path="">
<UserOverview />
</Route>
<Route path="edit">
<EditUser />
</Route>
<Route path="permissions">
<UserPermissions />
</Route>
</UserDetail>
</Route>
</UsersSection>
</Route>
</AdminLayout>
</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>
  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
<Route path="/dashboard">
<Route exact path="">
<DashboardHome />
</Route>
<Route path="analytics">
<Analytics />
</Route>
{/* This could serve as a fallback for unmatched paths under /dashboard */}
</Route>
// Handle both /posts and /posts/:id
<Route path="/posts">
<PostsLayout />
<Route exact path="">
<PostsList />
</Route>
<Route path=":id">
<PostDetail />
</Route>
</Route>
<Route path="/blog/:year/:month/:slug"> {/* /blog/2024/03/my-post */}
<Route path="/users/:userId"> {/* /users/123 */}
<Route path="/files/*path"> {/* /files/a/b/c - wildcard captures everything */}
<Route path="/api/:version/*rest"> {/* /api/v1/users/123 - combines params with wildcard */}

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"
}

Notes:

  • Wildcards must come at the end of the path
  • * matches at least one character (won’t match the exact base path)
  • /files/* matches /files/a but NOT /files
  • The matched path includes all slashes and segments