Skip to content

05 — Routing

Client-side routing with Routes, Route, Link, and useRouter. Browser history is handled automatically (Phase 5/6 of the router work).

tsx
import { Routes, Route, Link, useRouter } from 'flexium/router'

function Home() {
  return <h1>Welcome</h1>
}

function About() {
  return <h1>About us</h1>
}

function User() {
  const { params } = useRouter()
  return <h1>User #{params.id}</h1>
}

function NotFound() {
  return <h1>404</h1>
}

export function App() {
  return (
    <div>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/users/42">User 42</Link>
      </nav>

      <Routes>
        <Route path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/users/:id" component={User} />
        <Route path="*" component={NotFound} />
      </Routes>
    </div>
  )
}

Browser history

  • Clicking <Link to="/x"> calls history.pushState and updates the route signal.
  • Browser back/forward buttons fire popstate, which is handled internally.
  • Direct URL access works (e.g., loading /users/42 directly).

Dynamic params

:id in the path is captured into params.id. Access via:

tsx
function User() {
  const { params, location, navigate } = useRouter()
  // params.id      — string from URL
  // location.pathname — current path
  // navigate(path) — programmatic navigation
}

Nested routes

Use <Outlet /> for layout-with-child-routes patterns:

tsx
import { Routes, Route, Outlet, Link } from 'flexium/router'

function Layout() {
  return (
    <div>
      <header>My app</header>
      <Outlet />
    </div>
  )
}

<Routes>
  <Route path="/" component={Layout}>
    <Route path="/" component={Home} />
    <Route path="/about" component={About} />
  </Route>
</Routes>

Guards

Route guards via beforeEnter:

tsx
<Route
  path="/admin"
  component={Admin}
  beforeEnter={(params) => {
    if (!isLoggedIn()) {
      // returning false skips render — typically navigate elsewhere
      navigate('/login')
      return false
    }
    return true
  }}
/>

API surface used

  • <Routes>, <Route>, <Outlet>, <Link> — declarative routing
  • useRouter() — programmatic access (params, location, navigate)

Next

Fast signals — drop hook overhead to 13ns.

Released under the MIT License.