Skip to content

Free MIT template · Day 6 of 365

You're looking at a demo. Download the built static files (drop on any host) or grab the full source to customize.

↓ Download static ↓ Source (Astro) All 365 →Build with me →

# <Router /> (React adapter)

routekit ships a tiny optional React adapter: `<Router />`. It wraps the same `createRouter()` API but exposes it as a component, which is more familiar to teams already deep in React.

Tip

The adapter adds ~600 bytes. If you don’t use React, skip it — `createRouter()` directly is the framework-agnostic API.

## Import

    import { Router } from 'routekit/react';

The `routekit/react` subpath is tree-shakable. Importing only `Router` and `useRoute` lands at roughly 2.4 KB post-min+gzip in a real React bundle.

## Signature

    type RouterProps<T extends RouteDefinition[]> = {  routes: T;  base?: string;  fallback?: ReactNode;  onNavigate?: (match: Match<T>) => void;};
    function Router<T>(props: RouterProps<T>): JSX.Element;

## Props

Prop | Type | Default | Description
--- | --- | --- | ---
`routes` | `RouteDefinition[]` | — | Same shape as the bare API. Use `as const`.
`base` | `string` | `'/'` | Base path.
`fallback` | `ReactNode` | `null` | Rendered while a route handler is resolving.
`onNavigate` | `(match) => void` | — | Optional callback for analytics, logging, etc.

## Example

    import { Router, useRoute } from 'routekit/react';
    const routes = [  { path: '/',           handler: () => import('./pages/Home') },  { path: '/posts/:id',  handler: () => import('./pages/Post') },] as const;
    export default function App() {  return (    <Router routes={routes} fallback={<Spinner />}>      <AppShell>        <Outlet />      </AppShell>    </Router>  );}
    // In Outlet:function Outlet() {  const { match, Page } = useRoute();  if (!Page) return null;  return <Page params={match.params} />;}

## How it works

The component:

1. Calls `createRouter(routes, { base })` once on mount.
2. Subscribes to `navigate` events and stores `{ match, Page }` in React state via `useState` + `useEffect`.
3. Provides them via Context to descendants reading `useRoute()`.
4. Renders `fallback` while a chunk is resolving.
5. Tears down the router subscription on unmount.

There’s no magic. If you want to see the source it’s about 90 lines.

## When to use the React adapter

- You want JSX. Mounting `<Router />` and reading `useRoute()` feels native to React apps.
- You want `<Suspense />` integration. The adapter handles the chunk-loading boundary so you don’t have to wire it manually.
- You want React-DevTools-friendly route changes. Each navigation triggers a normal React state update; route changes show up cleanly in profiling.

## When to skip it

- You’re not using React. Use `createRouter()` directly.
- Your bundle budget is brutal. ~600 bytes is small but non-zero.
- You want to manage the lifecycle yourself. The bare API gives you cleanup callbacks, manual `start()`/`stop()`, etc. The adapter takes those choices away.

## Caveats

- The adapter doesn’t ship with a `<Link>` component. Use plain `<a href="...">` — routekit intercepts clicks at the document level. See navigation.
- `useRoute()` returns `null` on first render, before the initial route resolves. Always null-check.
- The adapter is React-only. There’s no Vue / Solid / Preact adapter shipped — for those, write 30 lines yourself or use `createRouter()` directly with your framework’s lifecycle hooks.