Skip to content

Router

A lightweight, React-based client-side router with support for nested routes, path parameters, and immutable search parameter handling.

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
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>
);
}

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 history
router.replace("/login"); // Replace current entry

Access 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/:postId
const 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";

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>

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 */}

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().

Safely update URL search parameters without mutations:

const searchParams = useSearchParams();
const withFilter = searchParams.set("category", "electronics");
const withSort = withFilter.set("sort", "price");

Provide custom location and history for predictable tests:

<Router
location={{ pathname: "/users/123", search: "?tab=profile", hash: "#bio" }}
history={mockHistory}
>
<App />
</Router>
function NavLink({ href, children }) {
const pathname = usePathname();
const isActive = pathname === href;
return (
<Link
href={href}
className={isActive ? 'nav-link active' : 'nav-link'}
>
{children}
</Link>
);
}
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>
);
}

For detailed API documentation, see the individual component and hook documentation files linked above.