Routing
The router in Refract is more than just a simple mapping of URLs to components.
At the advanced level, it acts as a navigation engine with hooks, middleware, and lifecycle events you can extend.
- How the router lifecycle works internally
- Writing custom navigation guards and middlewares
- Lazy loading and route-based code splitting
- Handling nested and dynamic routes
- Advanced features: scroll behavior, route meta, and error handling
Router Lifecycle
When a navigation is triggered, the router processes it through several stages:
- Resolve → Match the incoming path against the route table.
- Before Hooks → Run global and per-route guards.
- Component Mount → Render matched components.
- After Hooks → Trigger side-effects like analytics or logging.
This lifecycle gives you multiple extension points.
Global Navigation Guards
Global guards allow you to intercept every route change and enforce app-wide rules.
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !auth.isLoggedIn()) {
next("/login");
} else {
next();
}
});
Middleware-Style Plugins
You can inject middlewares into the router for modular logic:
function analyticsPlugin(router) {
router.afterEach((to) => {
trackPageView(to.fullPath);
});
}
router.use(analyticsPlugin);
Nested & Dynamic Routes
Advanced routing often requires deeply nested views or dynamic parameters.
const routes = [
{
path: "/dashboard",
component: Dashboard,
children: [
{ path: "settings", component: Settings },
{ path: "users/:id", component: UserProfile },
],
},
];
Dynamic routes like /users/42 automatically expose parameters (id) inside the component.
Lazy Loading & Code Splitting
For performance, load components only when needed:
const routes = [
{
path: "/settings",
component: () => import("./views/Settings.js"),
},
];
This ensures faster initial load and smaller bundles.
Scroll Behavior
Customize scroll restoration between navigations:
const router = createRouter({
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition;
return { top: 0 };
},
});
Error Handling
Catch navigation errors gracefully:
router.onError((err) => {
console.error("Routing error:", err);
router.push("/error");
});
Summary
The advanced router APIs give you fine-grained control over navigation, user experience, and app performance. By mastering lifecycle hooks, lazy loading, and middleware, you can build routing systems that are scalable, resilient, and optimized for users.