# Navigation and URL State

> Navigate with Link and navigate(), and keep URL-owned state in the URL rather than mirroring it into component state.

Source: [https://askrjs.com/docs/routing/navigation-and-url-state](https://askrjs.com/docs/routing/navigation-and-url-state)

Status: stable. Packages: @askrjs/askr.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

Keep shareable filters in route search state so refresh, history, and copied URLs preserve the same view.

```tsx
import { currentRoute, updateRouteQuery } from '@askrjs/askr/router';

const route = currentRoute();
const status = () => route.query.get('status') ?? 'active';

updateRouteQuery({ status: 'paused', page: 1 });
```

## Link and navigate

`Link` renders a real `<a>` element and intercepts clicks to route through `navigate()` instead of a full page load, while still respecting middle-click, Ctrl/Cmd-click, Shift-click, and Alt-click so the native "open in new tab" and "download" behaviors keep working. It accepts either an `href` string or a typed `to` destination — never both — plus the usual `rel`, `target`, and `aria-current` props. For navigation triggered from code rather than a click — after a form submits, say — call `navigate(path, options)` directly with the same `history` and `scroll` options `Link` uses internally.

## Search parameters

`updateRouteQuery(updates, options?)` patches the current URL's query string without a full navigation: pass a plain object of key-value updates, or a function that receives the live `URLSearchParams` for finer control like deleting a key conditionally. It defaults to `history: 'replace'` specifically so wiring it up to a search input doesn't produce a browser-history entry per keystroke. Reading the query back happens through `RouteQuery` on the current snapshot, which exposes `get()`, `getAll()`, `has()`, and `toJSON()` rather than a raw `URLSearchParams` instance.

## History and scroll

`NavigateOptions.history` is `'push'` or `'replace'`, controlling whether the navigation adds a new browser-history entry or overwrites the current one; `replace: true` is shorthand for the same thing. Scroll behavior is separate: `NavigationScrollBehavior` (`'top'` or `'preserve'`) governs what a fresh navigation does, while `HistoryScrollBehavior` (`'restore' | 'top' | 'preserve'`) governs back/forward navigation specifically, since users generally expect scroll position to come back on browser-back but not on a forward click to a new page. `ScrollRestorationOptions` is app-wide configuration set once through `configureScrollRestoration()`, not a per-navigation option — `NavigateOptions` itself has its own narrower `scroll` field for overriding forward-navigation behavior on a single call, but there's no equivalent per-call override for back/forward scroll restoration.

## Active route state

`currentRoute()` returns a `RouteSnapshot` with the matched `path`, typed `params`, `query`, `hash`, and a `matches` array covering every layout and page that contributed to the current render — useful for building breadcrumbs or highlighting the active section of a nav. It's synchronous, reflects whatever finished resolving most recently, and must be called during component render execution — calling it from outside render (a plain callback, module scope) throws rather than returning a stale snapshot. Pair it with `aria-current="page"` on `Link` when you need visually distinct "you are here" styling that also communicates correctly to screen readers.

## Documentation navigation

[Previous](https://askrjs.com/docs/routing/paths-and-parameters/index.md) | [Next](https://askrjs.com/docs/routing/loaders-and-deferred/index.md)
