Angular note: injectRouter() must be called within an injection context (constructor or field initializer). Returns the Router instance directly -- not a signal.
Basic Example
functionMyComponent(){constrouter=useRouter();consthandleClick=()=>{router.navigate("users.profile",{id: "123"});};return<buttononClick={handleClick}>Go to Profile</button>;}
3. Parameters
Hook accepts no parameters.
4. Return Value
Type: Router
Description: Router instance from @real-router/core
Main Router Methods
Method
Description
navigate(name, params?, options?)
Navigate to route
start()
Start router
stop()
Stop router
subscribe(listener)
Subscribe to changes (low-level)
subscribeLeave(listener)
Subscribe to confirmed departures
isLeaveApproved()
True in LEAVE_APPROVED phase
getState()
Get current state
buildPath(name, params?)
Build URL for route
isActive(name, params?, options?)
Check if route is active
5. Dependencies and Context
Required Providers
Provider
Required
Description
RouterProvider
Yes
Must wrap the component using the hook
Used Hooks
useContext(RouterContext) — getting router instance from context
6. Re-render Behavior
Reference stability: router — stable reference, doesn't change between renders
Update triggers: Hook does NOT cause re-renders on navigation
Memoization: Not required — return value is already stable
Important: Unlike useRoute, the useRouter hook does not subscribe to router state changes. A component using only useRouter will not re-render on navigation.
7. Possible Errors
Condition
Error
How to Avoid
Hook called outside RouterProvider
"useRouter must be used within a RouterProvider"
Wrap component in RouterProvider
8. Behavior
Main Scenarios
Returns the same router instance passed to RouterProvider
Throws error when provider is missing
Edge Cases
Router doesn't need to be started (start()) for hook to work
Guarantees
Hook returns referentially stable router instance
Fail-fast behavior when provider is missing
9. Related Hooks
Hook
When to Use Instead
useRoute
When you need current route access and automatic re-renders on navigation
useRouteNode
When you need subscription only to specific route node
functionFormComponent(){constrouter=useRouter();consthandleSubmit=async(data)=>{awaitapi.saveData(data);// replace: true — doesn't add entry to historyrouter.navigate("success",{},{replace: true});};return<formonSubmit={handleSubmit}>...</form>;}
Auto-Save on Confirmed Departure
functionEditorComponent(){constrouter=useRouter();useEffect(()=>{// Auto-save form draft when leaving (only if departure confirmed)constunsub=router.subscribeLeave(({ route })=>{if(route.name==="editor"){localStorage.setItem("editor:draft",getEditorContent());}});returnunsub;},[router]);return<textareaplaceholder="Edit content..."/>;}
Anti-patterns
// Don't use useRouter to get current routefunctionBad(){constrouter=useRouter();conststate=router.getState();// Not reactive! Component won't update on navigationreturn<div>{state?.name}</div>;}// Use useRoute for reactive route accessfunctionGood(){const{ route }=useRoute();return<div>{route?.name}</div>;}
// Don't subscribe manually via router.subscribefunctionBad(){constrouter=useRouter();const[route,setRoute]=useState(router.getState());useEffect(()=>{returnrouter.subscribe(({ route })=>setRoute(route));},[router]);return<div>{route?.name}</div>;}// Use useRoute — it already does this correctlyfunctionGood(){const{ route }=useRoute();return<div>{route?.name}</div>;}
// Don't pass router via props to deep componentsfunctionBad(){constrouter=useRouter();return<DeepChildrouter={router}/>;}// Use useRouter in child componentfunctionGood(){return<DeepChild/>;// DeepChild will call useRouter() itself}
11. Migration from router5
Comparison of @real-router/react/useRouter with react-router5/useRouter from router5.
Version Comparison
router5 (react-router5)
Real Router (@real-router/react)
Export
export default function useRouter()
export const useRouter
Signature
useRouter(): Router
useRouter(): Router
Router type
router5.Router
@real-router/core Router
1. Breaking Changes
Severity
What Changed
Was
Now
Impact
CRITICAL
Export type
export default
export const (named)
All imports will break
HIGH
Context validation
Returns undefined if no provider
Throws Error
Code without provider will crash
MEDIUM
Router type
router5.Router
@real-router/core
Router API may differ
Parameter Changes
Hook accepts no parameters — no changes.
Return Value Changes
Field
Change
Migration
Router type
router5.Router → @real-router/core Router
Check router API compatibility
Examples
// Code that will break (import)importuseRouterfrom"react-router5";// Code after migrationimport{useRouter}from"@real-router/react";
// Code that will break (without provider)functionOrphan(){constrouter=useRouter();// Previously returned undefinedrouter?.navigate("home");// Worked with optional chaining}// Code after migration — ensure provider exists// Now throws error: "useRouter must be used within a RouterProvider"
2. Implementation Changes
New Behavior
Fail-fast validation: Hook now throws clear error "useRouter must be used within a RouterProvider" if called outside provider. Previously returned undefined, causing implicit errors later.