Router
A lightweight, React-based client-side router with support for nested routes, path parameters, and immutable search parameter handling.
Overview
Section titled “Overview”The @farbenmeer/router package provides a very lightweight routing solution for React applications with the following key features:
- Declarative routing with React components
- Nested routes with parameter inheritance
- Path parameters with colon syntax (
:id) - Wildcard routes for catch-all paths (
*and*name) - Immutable search parameters for predictable state management
- Client-side navigation with history management
- TypeScript support for better development experience
- Testing-friendly with customizable location and history
Quick Start
Section titled “Quick Start”import { Router, Route, Link } from "@farbenmeer/router";
function App() { return ( <Router> <nav> <Link href="/">Home</Link> <Link href="/users">Users</Link> <Link href="/about">About</Link> </nav>
<main> <Route path="/"> <HomePage /> </Route>
<Route path="/users"> <UsersLayout /> <Route exact> <UsersList /> </Route> <Route path=":id"> <UserProfile /> </Route> </Route>
<Route path="/about"> <AboutPage /> </Route> </main> </Router> );}Components
Section titled “Components”The root component that provides routing context to your application.
- Manages current location state
- Provides navigation methods
- Supports custom location and history for testing
- Normalizes pathnames (removes trailing slashes)
Conditionally renders content based on the current pathname.
- Path matching with parameters (
/users/:id) - Wildcard matching (
/files/*or/files/*path) - Exact matching option
- Nested route support
- Parameter inheritance from parent routes
Declarative navigation component that renders as an anchor element.
- Client-side navigation with history management
- Supports absolute and relative paths
- Query parameter handling
Provides programmatic navigation methods.
const router = useRouter();router.push("/users/123"); // Navigate with historyrouter.replace("/login"); // Replace current entryAccess the current pathname for conditional rendering and active states.
const pathname = usePathname();const isActive = pathname === "/users";Access and manipulate URL search parameters with immutable methods.
const searchParams = useSearchParams();const query = searchParams.get("q");const newParams = searchParams.set("filter", "active");Extract parameters from dynamic route segments.
// Route: /users/:id/posts/:postIdconst params = useParams(); // { id: "123", postId: "456" }Access the current URL hash fragment for tab navigation and anchor linking.
const hash = useHash();const activeTab = hash.slice(1) || "overview";Key Features
Section titled “Key Features”Nested Routing
Section titled “Nested Routing”Create hierarchical route structures with parameter inheritance:
<Route path="/organizations/:orgId"> <OrganizationLayout />
<Route path="teams/:teamId"> <TeamLayout />
<Route path="members/:memberId"> <MemberProfile /> </Route> </Route></Route>Path Parameters
Section titled “Path Parameters”Define dynamic segments with colon syntax:
<Route path="/users/:id"> {/* /users/123 */}<Route path="/posts/:slug"> {/* /posts/hello-world */}<Route path="/api/:version"> {/* /api/v1 */}Wildcard Routes
Section titled “Wildcard Routes”Match arbitrary paths with wildcards:
<Route path="/files/*"> {/* Matches /files/a, /files/a/b/c, etc. */}<Route path="/docs/*path"> {/* Matches and captures as params.path */}<Route path="/api/:version/*rest"> {/* Combines params with wildcards */}The * wildcard matches everything including slashes, making it perfect for catch-all routes. Use *name to capture the matched path as a parameter accessible via useParams().
Immutable Search Parameters
Section titled “Immutable Search Parameters”Safely update URL search parameters without mutations:
const searchParams = useSearchParams();const withFilter = searchParams.set("category", "electronics");const withSort = withFilter.set("sort", "price");Testing Support
Section titled “Testing Support”Provide custom location and history for predictable tests:
<Router location={{ pathname: "/users/123", search: "?tab=profile", hash: "#bio" }} history={mockHistory}> <App /></Router>Common Patterns
Section titled “Common Patterns”Active Navigation Links
Section titled “Active Navigation Links”function NavLink({ href, children }) { const pathname = usePathname(); const isActive = pathname === href;
return ( <Link href={href} className={isActive ? 'nav-link active' : 'nav-link'} > {children} </Link> );}Search and Filtering
Section titled “Search and Filtering”function ProductSearch() { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams();
const updateFilter = (key: string, value: string) => { const newParams = searchParams.set(key, value); router.push(`${pathname}?${newParams.toString()}`); };
return ( <select onChange={(e) => updateFilter("category", e.target.value)}> <option value="">All Categories</option> <option value="electronics">Electronics</option> </select> );}API Reference
Section titled “API Reference”For detailed API documentation, see the individual component and hook documentation files linked above.