Since React does not have a dedicated @esmx/router integration package, you implement your own hooks and context providers using standard React patterns. This page documents the recommended implementation for useRouter(), useRoute(), and RouterProvider.
router: Router — Router instance to providechildren: React.ReactNode — Child componentsJSX.ElementContext provider component that makes the router instance available to all descendant components via useRouter() and useRoute().
import { createContext } from 'react';
import type { Router } from '@esmx/router';
const RouterContext = createContext<Router | null>(null);
export function RouterProvider({
router,
children
}: {
router: Router;
children: React.ReactNode;
}) {
return (
<RouterContext.Provider value={router}>
{children}
</RouterContext.Provider>
);
}RouterError — If called outside a RouterProviderGets the router instance via React context. Equivalent to useRouter() in @esmx/router-vue.
import { useContext } from 'react';
import type { Router } from '@esmx/router';
export function useRouter(): Router {
const router = useContext(RouterContext);
if (!router) {
throw new Error('useRouter must be used within a RouterProvider');
}
return router;
}function NavigationButtons() {
const router = useRouter();
return (
<div>
<button onClick={() => router.push('/home')}>Home</button>
<button onClick={() => router.back()}>Back</button>
</div>
);
}RouteError — If called outside a RouterProviderGets the current reactive route object. Uses useSyncExternalStore for optimal React integration — the component re-renders automatically when the route changes. Equivalent to useRoute() in @esmx/router-vue.
import { useSyncExternalStore } from 'react';
import type { Route } from '@esmx/router';
export function useRoute(): Route {
const router = useRouter();
return useSyncExternalStore(
(callback) => router.afterEach(callback),
() => router.route,
() => router.route
);
}function CurrentPath() {
const route = useRoute();
return (
<div>
<p>Path: {route.path}</p>
<p>Params: {JSON.stringify(route.params)}</p>
<p>Query: {JSON.stringify(route.query)}</p>
</div>
);
}Complete reference implementation combining all hooks and the provider:
import { createContext, useContext, useSyncExternalStore } from 'react';
import type { Router, Route } from '@esmx/router';
// Context
const RouterContext = createContext<Router | null>(null);
// Provider
export function RouterProvider({
router,
children
}: {
router: Router;
children: React.ReactNode;
}) {
return (
<RouterContext.Provider value={router}>
{children}
</RouterContext.Provider>
);
}
// Hooks
export function useRouter(): Router {
const router = useContext(RouterContext);
if (!router) {
throw new Error('useRouter must be used within a RouterProvider');
}
return router;
}
export function useRoute(): Route {
const router = useRouter();
return useSyncExternalStore(
(callback) => router.afterEach(callback),
() => router.route,
() => router.route
);
}