Navigation and Links
Purpose and Scope
Navigation in TanStack Router is the shared model for moving from one route location to another, whether the user clicks an anchor rendered by the framework package or application code calls a function in response to an event. The navigation guide frames every navigation as relative: there is always an origin and a destination. That rule matters even when the destination looks absolute, because the router uses the origin to provide type-safe completion, parameter inference, search validation, and route matching behavior. This page explains the common options once, then applies them to links, imperative navigation, and active-route checks.
Sources: docs/router/guide/navigation.md
The practical reader problem is deciding which navigation surface to use. Use the Link component for normal user-initiated navigation that should render as an anchor and participate in browser expectations such as opening in a new tab. Use the navigate function returned by useNavigate when navigation is part of an event handler, a command button, a form flow, or a non-anchor interaction. Use useMatchRoute when you need to ask whether a destination matches the current or pending location, commonly for custom active states, menus, breadcrumbs, or conditional UI around routes.
Sources: docs/router/api/router/linkComponent.md, docs/router/api/router/useNavigateHook.md, docs/router/api/router/useMatchRouteHook.md
Relevant Source Files
- docs/router/guide/navigation.md — Defines the shared navigation model, relative navigation terminology, and the ToOptions and ToMaskOptions contracts used across navigation and route matching APIs.
- docs/router/api/router/linkComponent.md — Documents the Link component, its props shape, its anchor-element return value, examples for params and search updates, and path parameter encoding behavior.
- docs/router/api/router/useNavigateHook.md — Documents the useNavigate hook, the optional from option, the returned navigate function, the NavigateOptions argument, and the promise returned after navigation completes.
- docs/router/api/router/useMatchRouteHook.md — Documents the useMatchRoute hook, the returned matchRoute function, matching against current or pending locations, fuzzy matching, parameter filters, and false results for non-matches.
Core Navigation Model
The core concept is the pair of from and to. The from value identifies the route path or route id that should be treated as the origin. The to value identifies the destination route path, which can be absolute or relative to that origin. The guide warns that when from is not supplied, the router assumes navigation starts at the root route. In that mode, only absolute paths can be auto-completed and type-safe. Supplying a route full path as the origin is therefore not cosmetic; it gives TypeScript and the router enough context to understand relative movement through the route tree.
Sources: docs/router/guide/navigation.md
TanStack Router intentionally reuses one navigation vocabulary across APIs. The guide names ToOptions as the core interface behind navigation and route matching. That interface includes path movement through to, path interpolation through params, URL query updates through search, fragment updates through hash, history state through state, and optional URL masking through mask. The important constraint is that dynamic params, search, and hash are not meant to be interpolated into the to string. The route path remains a route pattern, while the structured options provide the data needed to build the final browser URL.
Sources: docs/router/guide/navigation.md
Declarative Links
Link is the declarative component for rendering a navigable anchor. The API reference describes it as a component that navigates to a new location, including pathname, search params, hash, and location state. Its props are LinkProps plus React anchor ref attributes, and it returns an anchor element. That anchor result is important for accessibility and browser behavior: use Link for ordinary navigation controls that are visually or semantically links, then pass the same structured route options described by the navigation guide instead of manually composing strings.
Sources: docs/router/api/router/linkComponent.md
A typical Link points at a route pattern and supplies dynamic segments separately. For example, a route path can contain a parameter placeholder, while params supplies the value and search can be expressed as a function of the previous search object. That pattern keeps the path definition stable and lets the router encode values, preserve or replace search state intentionally, and type-check required pieces. The Link reference also documents default path parameter encoding: characters such as at signs are encoded in generated URLs unless the router configuration allows them through the path parameter allowed-character setting.
Sources: docs/router/api/router/linkComponent.md
import { Link } from '@tanstack/react-router'
function PostLink() {
return (
<Link
from="/posts"
to="/posts/$postId"
params={{ postId: '123' }}
search={(prev) => ({ ...prev, preview: true })}
hash="comments"
state={{ openedFrom: 'list' }}
>
Open post
</Link>
)
}Imperative Navigation
useNavigate is the imperative companion to Link. The hook returns a navigate function that can move to a new location and can change pathname, search params, hash, and location state. The hook itself accepts an options object with an optional from value. Supplying from at hook creation is useful when every navigation in a component should be interpreted from the same route, such as a posts page that changes only its page search parameter. The returned navigate function accepts a NavigateOptions object and returns a promise that resolves when navigation is complete.
Sources: docs/router/api/router/useNavigateHook.md
Imperative navigation is best for actions, not for replacing anchors everywhere. A button that applies a saved filter, a menu item that advances a wizard, or an event handler that moves after a successful mutation can call navigate with the same route options used by Link. The reference examples show navigation to a pathname, navigation with search, navigation with a hash, and navigation with history state. That consistency reduces special cases: once an application has chosen how to represent route params and search params, both declarative and imperative navigation can share the same destination objects and type expectations.
Sources: docs/router/api/router/useNavigateHook.md
import { useNavigate } from '@tanstack/react-router'
function PostsPager() {
const navigate = useNavigate({ from: '/posts' })
return (
<button onClick={() => navigate({ search: { page: 2 } })}>
Page 2
</button>
)
}Route Matching and Active States
useMatchRoute supports the other half of navigation: checking whether a route pattern matches the current or pending location. The hook returns a matchRoute function. That function accepts matching options and returns the matched params or false when no route is matched. Because it can return the route parameters, it is useful for more than a boolean active flag. A navigation item can inspect whether a concrete entity route is active, a tab can confirm a parameter value, or a pending transition can be detected before the browser location has fully changed.
Sources: docs/router/api/router/useMatchRouteHook.md
The matching examples show several important edge cases. A current location of a nested post route does not exactly match the parent posts route unless fuzzy matching is requested. Passing fuzzy true allows a broader parent-style match and returns an empty parameter object when the parent route is active by containment. Matching can also be performed against the pending location, which is useful during transitions. Parameter filters narrow a match: if the current URL contains one post id but the supplied params require another, matchRoute returns false instead of returning unrelated route data.
Sources: docs/router/api/router/useMatchRouteHook.md
import { useMatchRoute } from '@tanstack/react-router'
function NavItem() {
const matchRoute = useMatchRoute()
const postMatch = matchRoute({ to: '/posts/$postId', pending: true })
return postMatch ? <span>Opening post {postMatch.postId}</span> : null
}Common Patterns and Edge Cases
For consistent navigation, start by choosing the narrowest reliable origin. In route components, that often means passing the current route full path as from or configuring useNavigate with a stable from value. Then keep path variables out of to and put them in params. Keep durable, shareable state in search, short page fragments in hash, and non-URL transition metadata in history state. This separation mirrors the source contracts and avoids brittle string concatenation, especially when paths contain encoded characters or when search params are validated elsewhere in the route tree.
Sources: docs/router/guide/navigation.md, docs/router/api/router/linkComponent.md, docs/router/api/router/useNavigateHook.md
Another common pattern is to build higher-level navigation components around the shared options contract. A design-system link can accept the same destination pieces that Link accepts, render application styling, and use useMatchRoute internally for active styling. When doing this, preserve the distinction between exact and fuzzy matching. Exact matching is appropriate for leaf links where a child route should not activate the parent item. Fuzzy matching is appropriate for sidebar sections, parent tabs, and route groups that should remain highlighted while a nested child is visible or while a pending navigation is moving into that section.
Sources: docs/router/api/router/linkComponent.md, docs/router/api/router/useMatchRouteHook.md
Compact API Reference
| API | Primary role | Key inputs | Result |
|---|---|---|---|
| Link | Declarative anchor navigation | LinkProps with to, params, search, hash, state, and related navigation props | An anchor element that navigates to the resolved location |
| useNavigate | Imperative navigation from components | Optional hook options with from; navigate options using NavigateOptions | A navigate function; each call returns a promise after completion |
| useMatchRoute | Route matching for current or pending locations | Match options such as to, params, fuzzy, and pending | Matched params object or false |
| ToOptions | Shared destination contract | from, to, params, search, hash, state, and mask | A typed description of where navigation or matching should resolve |
Next Steps
After learning the shared navigation shape, continue with pages that deepen each option. Read Path Params before relying on dynamic segments, Search Params before storing typed URL state, Custom Links and Link Options before designing reusable navigation components, and Route Masking and URL Rewrites before using the mask option for alternate browser URLs. For debugging active states or unexpected destinations, compare the from and to values first, then inspect whether params and search are being supplied structurally instead of embedded into strings.