Skip to content

React Router

A configuration-based router for React. Routes are registered as data on a singleton (router.add("/users/:id", UserPage)), rendered by one internal wrapper, and reach into browser globals (history, popstate, location) directly. Trades the composability of JSX routes for a simpler mental model: one global table, one render path, one place for middleware and lazy-loading.

Highlighted features

Routes as data

router.add(“/users/:id”, UserPage) on a singleton. One global table; refactor without touching JSX trees.

Locale-aware URLs

/en/admin/users, /fr/admin/users generated from one route declaration. changeLocaleCode swaps the prefix without re-mounting.

Middleware per route

Array of components returning null / NAVIGATING / ReactNode. Auth guards, role checks, redirect-before-render — composable per route or per group.

Lazy apps + modules

setApps([…]) wires app/module loader pairs. Code-splits at the route boundary; bundles per app instead of per page.

Prefetch on <Link> hover

Lazy chunks start loading the moment the user hovers a link. Opt out per-link with prefetch={false} when bandwidth matters.

Chunk-error recovery

lazyLoading.chunkErrorHandler recovers after deploys when a stale tab requests a hashed chunk that no longer exists. Hard-reload, fallback page, custom — your choice.

Install

Terminal window
npm install @mongez/react-router

Peer deps: react >= 18, react-dom >= 18.

Quick peek

import router, { Link, setRouterConfigurations } from "@mongez/react-router";
router.add("/", HomePage);
router.add("/users/:id", UserPage, [authMiddleware]);
setRouterConfigurations({
localization: { defaultLocaleCode: "en", localeCodes: ["en", "fr"] },
});
router.scan(); // mounts <RouterWrapper> into #root
// In any component:
<Link to="/users/42">User 42</Link>

Register routes as data on the singleton, configure locale-prefixed URLs, then call router.scan() to mount the renderer.

Mental model

declare router.add("/users/:id", UserPage);
router.add("/about", AboutPage, [authMiddleware]);
configure setRouterConfigurations({ localization: {...}, lazyLoading: {...} });
boot router.scan(); // mounts <RouterWrapper> into #root
// parses URL, fires "navigating",
// renders the matching route
run <Link to="/about"> // intercepts clicks → router.goTo
navigateTo("/about") // imperative; from anywhere
popstate (back/forward) // detected automatically
router.refresh(mode)
"navigating" + "rendering" events
<RouterWrapper> picks route, runs middleware, renders

One wrapper handles every navigation type. Middleware, lazy-loading, and not-found handling all live inside that one render path.

Scope vs. alternatives

NeedThis packageAlternative
Tree-shape routing (<Routes> / <Route> JSX)✗ — singleton-imperativereact-router-dom
Data loaders & actions with route-level revalidation✗ — bring your own (@mongez/atomic-query for cache)react-router@6.4+ data API
Type-safe paths (compile-time URL params)✗ — params are Record<string, any>@tanstack/router
Lazy-loaded app + module providersDIY with React.lazy
Locale prefix in path (/en/admin/users)DIY
Chunk-error recovery after deploysDIY
Prefetch lazy chunks on <Link> hoverDIY
Middleware per route + per groupreact-router@6.4+ loaders, @tanstack/router beforeLoad

Where to go next

  • Routesrouter.add, route shapes, dynamic segments
  • NavigationLink, navigateTo, navigateBack, silentNavigation
  • Params — URL params, query-string integration
  • Lazy loadingsetApps, app/module loader pairs, prefetch
  • Localization — locale-prefixed URLs, changeLocaleCode
  • Recipes — common patterns