Router

Client-side routing system with history management, dynamic routes, and focus-aware navigation for Smart TV apps.

Import

import {
RouterProvider,
Route,
Link,
useRouter,
useParams,
useRoute,
useLocation
} from '@smart-tv/ui';

Basic Usage

import { AppProvider, RouterProvider, Route, Screen } from '@smart-tv/ui';
function HomeScreen() {
return (
<Screen focusKey="home" selFocus>
<h1>Home Screen</h1>
</Screen>
);
}
function AboutScreen() {
return (
<Screen focusKey="about" selFocus>
<h1>About Screen</h1>
</Screen>
);
}
function App() {
return (
<AppProvider>
<RouterProvider initial="/">
<Route path="/" component={HomeScreen} />
<Route path="/about" component={AboutScreen} />
</RouterProvider>
</AppProvider>
);
}

Dynamic Routes with Parameters

Use :param syntax for dynamic route segments.

import { useParams } from '@smart-tv/ui';
function PlayerScreen() {
const { id } = useParams<{ id: string }>();
return (
<Screen focusKey="player" selFocus>
<h1>Playing video: {id}</h1>
</Screen>
);
}
function App() {
return (
<AppProvider>
<RouterProvider initial="/">
<Route path="/" component={HomeScreen} />
<Route path="/player/:id" component={PlayerScreen} />
<Route path="/category/:categoryId/video/:videoId" component={DetailScreen} />
</RouterProvider>
</AppProvider>
);
}

Navigation with Link Component

import { Link, Button } from '@smart-tv/ui';
function HomeScreen() {
return (
<Screen focusKey="home">
<h1>Home</h1>
{/* Link as a focusable button */}
<Link to="/about" focusKey="about-link">
<Button>Go to About</Button>
</Link>
{/* Link with parameters */}
<Link to="/player/123" focusKey="player-link">
<Button>Watch Video 123</Button>
</Link>
{/* Link with state */}
<Link
to="/details"
state={{ videoData: { title: 'My Video' } }}
focusKey="details-link"
>
<Button>View Details</Button>
</Link>
</Screen>
);
}

Programmatic Navigation

Use the useRouter hook for programmatic navigation.

import { useRouter, Button } from '@smart-tv/ui';
function HomeScreen() {
const router = useRouter();
const handleNavigate = () => {
// Navigate to a route
router.push('/about');
// Navigate with parameters
router.push('/player/456');
// Navigate with state
router.push('/details', { videoId: '789' });
// Go back
router.back();
// Replace current route (no history entry)
router.replace('/login');
// Check if can go back
if (router.canGoBack()) {
router.back();
}
};
return (
<Screen focusKey="home">
<Button focusKey="nav-button" onEnterPress={handleNavigate}>
Navigate
</Button>
</Screen>
);
}

Router Configuration

Configure router behavior with advanced options.

<RouterProvider
initial="/"
maxStack={10} // Limit history stack size
collapseSameBase={true} // Collapse routes with same base path
skipDuplicates={true} // Skip duplicate consecutive routes
>
<Route path="/" component={HomeScreen} />
<Route path="/about" component={AboutScreen} />
</RouterProvider>

Skippable Routes

Mark routes as skippable to bypass them when navigating back.

<RouterProvider initial="/">
<Route path="/" component={HomeScreen} />
{/* Loading screen will be skipped when going back */}
<Route path="/loading" component={LoadingScreen} skippable />
<Route path="/player/:id" component={PlayerScreen} />
</RouterProvider>
// When user goes from Home -> Loading -> Player
// and presses back, they'll return directly to Home, skipping Loading

useRoute Hook

Get current route information and state.

import { useRoute } from '@smart-tv/ui';
function MyScreen() {
const route = useRoute();
console.log(route.path); // Current path: "/player/123"
console.log(route.params); // Params: { id: "123" }
console.log(route.state); // Any state passed during navigation
console.log(route.skippable); // Whether route is skippable
return <div>Current path: {route.path}</div>;
}

useLocation Hook

Get current location information.

import { useLocation } from '@smart-tv/ui';
function Navigation() {
const location = useLocation();
return (
<nav>
<Link
to="/"
className={location.pathname === '/' ? 'active' : ''}
>
Home
</Link>
<Link
to="/about"
className={location.pathname === '/about' ? 'active' : ''}
>
About
</Link>
</nav>
);
}

Accessing Navigation State

// Passing state during navigation
function HomeScreen() {
const router = useRouter();
const openPlayer = (video) => {
router.push('/player/123', {
videoTitle: video.title,
resumeTime: video.lastPosition
});
};
return <Button onEnterPress={() => openPlayer(myVideo)}>Play</Button>;
}
// Receiving state in destination route
function PlayerScreen() {
const route = useRoute();
const { videoTitle, resumeTime } = route.state || {};
return (
<div>
<h1>{videoTitle}</h1>
<p>Resume from: {resumeTime}s</p>
</div>
);
}

RouterProvider Props

PropTypeDefaultDescription
initialstringrequiredInitial route path
maxStacknumber50Max history stack size
collapseSameBasebooleanfalseCollapse same base paths
skipDuplicatesbooleanfalseSkip duplicate routes

Route Props

PropTypeDefaultDescription
pathstringrequiredRoute path pattern
componentComponentTyperequiredComponent to render
skippablebooleanfalseSkip when navigating back

useRouter Methods

MethodSignatureDescription
push(path, state?) => voidNavigate to path
replace(path, state?) => voidReplace current route
back() => voidGo back one route
canGoBack() => booleanCheck if can go back

Best Practices

  • Always wrap RouterProvider inside AppProvider
  • Use dynamic parameters (:id) for content-specific routes
  • Mark transient screens (loading, splash) as skippable
  • Pass complex data via state instead of URL parameters
  • Use replace() for redirects to avoid cluttering history
  • Each Screen component should have selFocus for proper focus management
  • Handle back button navigation with router.back() or browser back event