Deprecated: BaseLink was removed. Use Link directly — it supports all props including routeOptions. See Link.
1. Overview
Name: BaseLink
Status: Removed — all functionality merged into Link
Migration: Replace BaseLink with Link inside RouterProvider. The routeOptions prop is now supported directly on Link.
2. Import and Basic Usage
import{BaseLink,useRouter}from"@real-router/react";functionNavigation(){constrouter=useRouter();return(<nav><BaseLinkrouter={router}routeName="home">
Home
</BaseLink><BaseLinkrouter={router}routeName="users"activeClassName="current">
Users
</BaseLink></nav>);}
Parameters for URL building. Must match parameters in route definition.
<BaseLinkrouter={router}routeName="users.profile"routeParams={{id: "123"}}>
User 123
</BaseLink>
routeOptions
Router navigation options.
<BaseLinkrouter={router}routeName="checkout"routeOptions={{replace: true}}// Replaces current history entry>
Checkout
</BaseLink><BaseLinkrouter={router}routeName="dashboard"routeOptions={{reload: true}}// Forces reload>Dashboard</BaseLink>
activeClassName and activeStrict
Managing CSS class for active state.
// Non-strict check (default): "users" active for "users", "users.list", "users.profile"<BaseLinkrouter={router}routeName="users"activeClassName="nav-active"activeStrict={false}>
Users
</BaseLink>// Strict check: "users" active only for "users"<BaseLinkrouter={router}routeName="users"activeClassName="nav-active"activeStrict={true}>Users</BaseLink>
ignoreQueryParams
Managing query parameter check when determining activity.
// Ignores query params (default): active for /users?page=1<BaseLinkrouter={router}routeName="users"routeParams={{id: "123"}}ignoreQueryParams={true}>
User
</BaseLink>// Checks query params: requires exact match<BaseLinkrouter={router}routeName="users"routeParams={{id: "123",sort: "name"}}ignoreQueryParams={false}>User</BaseLink>
onClick
Custom click handler. Called before navigation.
<BaseLinkrouter={router}routeName="logout"onClick={(evt)=>{// Can cancel navigationif(!confirm("Are you sure?")){evt.preventDefault();}}}>
Logout
</BaseLink>
4. Children
Type: ReactNode
Description: Link content — text, icons, other components
Params stabilization is handled inside @real-router/sources (canonicalJson cache key in createActiveRouteSource) — inline routeParams literals don't defeat the cache.
9. Events
Event
Signature
Description
onClick
(evt: MouseEvent<HTMLAnchorElement>) => void
Link click
Click Handling Logic
onClick is called (if provided)
If evt.defaultPrevented — navigation is cancelled
shouldNavigate() is checked (left button, no modifiers)
If target="_blank" — navigation is not intercepted
router.navigate() is called
10. Behavior
Main Scenarios
Renders <a> with correct href based on routeName and routeParams
Adds activeClassName when route is active
Calls onClick on click
Navigates on left click without modifiers
Edge Cases
Does not navigate on right/middle mouse button
Does not navigate on click with Ctrl/Cmd/Shift/Alt
Does not navigate if onClick called preventDefault()
Does not navigate if target="_blank"
Uses buildUrl (if available) or buildPath for URL building
Updates href when routeName or routeParams change
Guarantees
Memoization via React.memo with custom comparator
Active-route cache in @real-router/sources is key-order-insensitive (canonical params hashing) — inline routeParams objects don't create duplicate subscriptions
Correct activeClassName operation with query parameters
11. Related Components
Component/Hook
Relationship
Link
Wrapper over BaseLink with automatic router retrieval
useIsActiveRoute
Used for activity check (internal hook)
useRouter
For getting router instance
12. Usage Examples
Basic Example
import{BaseLink,useRouter}from"@real-router/react";functionNavLink({ to, children }){constrouter=useRouter();return(<BaseLinkrouter={router}routeName={to}>{children}</BaseLink>);}
For per-navigation result handling, use router.navigate() directly instead of BaseLink:
functionCheckoutButton(){constrouter=useRouter();const[isNavigating,setIsNavigating]=useState(false);consthandleClick=async()=>{setIsNavigating(true);try{awaitrouter.navigate("checkout");analytics.track("checkout_started");}catch(err){toast.error(`Cannot proceed: ${err.message}`);}finally{setIsNavigating(false);}};return(<buttononClick={handleClick}disabled={isNavigating}>{isNavigating ? "Loading..." : "Proceed to Checkout"}</button>);}
Confirmation Before Navigation
functionDeleteLink({ itemId }){constrouter=useRouter();return(<BaseLinkrouter={router}routeName="items.delete"routeParams={{id: itemId}}onClick={(evt)=>{if(!window.confirm("Delete this item?")){evt.preventDefault();}}}>
Delete
</BaseLink>);}
Anti-patterns
// Don't pass new routeParams object on every renderfunctionBad({ userId }){constrouter=useRouter();return(<BaseLinkrouter={router}routeName="users.profile"routeParams={{id: userId}}// New object every time!>
Profile
</BaseLink>);}// Optional: memoize params for custom comparators / manual subscriptions.// For BaseLink itself, canonical-args cache in sources handles this already.functionGood({ userId }){constrouter=useRouter();constparams=useMemo(()=>({id: userId}),[userId]);return(<BaseLinkrouter={router}routeName="users.profile"routeParams={params}>
Profile
</BaseLink>);}
// Don't forget RouterProviderfunctionBad(){constrouter=createRouter(routes);return(<BaseLinkrouter={router}routeName="home">
Home
</BaseLink>);// Active route detection inside will throw error!}// Wrap in RouterProviderfunctionGood(){return(<RouterProviderrouter={router}><Navigation/></RouterProvider>);}
// Don't use for external linksfunctionBad(){return(<BaseLinkrouter={router}routeName="https://google.com">
Google
</BaseLink>);}// Use regular <a> for external linksfunctionGood(){return(<ahref="https://google.com"target="_blank"rel="noopener">
Google
</a>);}
Migration from router5
Version Comparison
router5
Real Router
File
modules/BaseLink.ts
modules/components/BaseLink.tsx
Architecture
Class Component
FC + memo with custom comparator
Props types
BaseLinkProps extends HTMLAttributes<...>
BaseLinkProps with [key: string]: unknown
Renders
<a> without data attributes
<a> with data-route and data-active
1. Breaking Changes
Severity Levels:
CRITICAL — Component will definitely break
HIGH — Component will likely break
MEDIUM — Component may break in some cases
LOW — Backward compatible, but needs attention
Changes Table
Severity
What Changed
Was
Now
Impact
HIGH
CSS class order
"active className"
"className active"
CSS selectors with :first-child or class order
CRITICAL
successCallback/errorCallback removed
Accepted props
Removed — use router.navigate() with try/catch
Code using navigation callbacks on links will break
MEDIUM
Prop route removed
Accepted
Ignored
Code passing route
LOW
Data attributes added
Missing
data-route, data-active
CSS/JS relying on DOM structure
Props Changes
Prop
Change
Migration
route
Removed
Remove passing this prop
onMouseOver
Moved to rest props
Works, but not in explicit types
successCallback
Removed
Use router.navigate() with try/catch
errorCallback
Removed
Use router.navigate() with try/catch
routeParams
Type { [key: string]: any } → Params
Use types from @real-router/core
Rendering Changes
Aspect
Was
Now
Class order
activeClassName className
className activeClassName
Data attributes
Missing
data-route={routeName}data-active={isActive}
className formation
split(' ').join(' ')
Template literal with .trim()
Examples
// Code that may break (CSS selectors by order).active:first-child{/* In router5 "active" was first */}// Code after migration (use independent selectors).active{/* Works regardless of order */}a[data-active="true"]{/* New way via data attribute */}
// Code that will break (passing route)<BaseLinkrouter={router}routeName="home"route={currentRoute}>
Home
</BaseLink>// Code after migration (route not needed)<BaseLinkrouter={router}routeName="home">Home</BaseLink>
2. Implementation Changes
Removed Props
route: Internal logic reworked, prop no longer used
successCallback: Removed — use router.navigate() with try/catch
errorCallback: Removed — use router.navigate() with try/catch
New Props
children: Explicitly added to types (previously inherited from HTMLAttributes)
Rendering Changes
data-route: Added attribute with route name for event delegation
data-active: Added attribute with boolean activity state for CSS selectors
Class order: Changed from activeClassName + className to className + activeClassName
Architectural Changes
Class → FC: Transition from class component to functional
memo: Added memoization with custom comparator for render optimization
Canonical params cache in sources: Reference stabilization for routeParams lives inside createActiveRouteSource (canonicalJson), shared by all adapters
useIsActiveRoute: Activity check logic extracted to separate internal hook
useMemo/useCallback: Memoization of href, className and handleClick
Typing Improvements
Params: Using type from @real-router/core instead of { [key: string]: any }
3. Dependency Changes
Dependency
Was
Now
router5
Yes
No
@real-router/core
No
Yes
React hooks
Not used
useMemo, useCallback, memo
useIsActiveRoute
Didn't exist
Used for activity check (internal)
@real-router/sources
Didn't exist
Provides cached createActiveRouteSource with canonicalJson params hashing
4. Migration Guide
Checklist
Remove passing prop route (if used)
Remove successCallback and errorCallback props — use router.navigate() with try/catch instead
Check CSS selectors depending on class order
Update imports from router5 to @real-router/core
Check CSS/JS relying on absence of data attributes
Step-by-Step Migration
Update imports: Replace router5 with @real-router/core in types and imports
Remove route prop: Find all places where route is passed and remove
Remove callback props: Replace successCallback/errorCallback with router.navigate() using try/catch
Check CSS: Ensure CSS selectors don't depend on class order
Use data attributes: Optionally — can use data-active instead of activeClassName for styling
5. Summary
Category
Status
Breaking Changes
CRITICAL (callback removal), HIGH (class order)
New props
None
Removed props
route, successCallback, errorCallback
DOM changes
data attributes
Accessibility
No changes
Maximum severity: CRITICAL — successCallback/errorCallback props removed; use router.navigate() with try/catch instead.