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">callshistory.pushStateand updates the route signal. - Browser back/forward buttons fire
popstate, which is handled internally. - Direct URL access works (e.g., loading
/users/42directly).
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 routinguseRouter()— programmatic access (params, location, navigate)
Next
→ Fast signals — drop hook overhead to 13ns.