# raviger
> React hook-based router. Zero dependencies, tiny footprint (~3KB), updates on **all** URL changes including browser back/forward. Supports React 16.8+.
Install: `npm i raviger`
## Core Concepts
Routes are plain objects mapping path strings to functions that return JSX. Path variables use `:name` syntax. Wildcards use `*`. Route functions receive path params as props.
## API
### `useRoutes(routes, options?)`
Main routing hook. Returns matched JSX element or `null`.
```jsx
import { useRoutes, Link } from 'raviger'
const routes = {
'/': () => ,
'/about': () => ,
'/users/:userId': ({ userId }) =>
}
export default function App() {
const route = useRoutes(routes)
return (
Home
About
{route}
)
}
```
Options:
- `basePath?: string` — prepend to all routes; sets context for nested hooks/Links
- `routeProps?: object` — extra props passed to matched route function
- `overridePathParams?: boolean` (default `true`) — routeProps override path params
- `matchTrailingSlash?: boolean` (default `true`) — `/about/` matches `/about`
Array form for explicit priority control:
```js
const routes = [
{ path: '/users/:id/edit', fn: ({ id }) => },
{ path: '/users/:id', fn: ({ id }) => },
]
```
---
### `navigate(url, options?)`
Programmatic navigation. Options: `{ replace?: boolean, query?: object, state?: unknown }`.
```js
import { navigate } from 'raviger'
navigate('/users/1')
navigate('/search', { query: { q: 'hello' } })
navigate('/replace-me', { replace: true })
```
---
### `useNavigate(basePath?)`
Hook version of `navigate` that respects `basePath` context.
```jsx
function Nav() {
const navigate = useNavigate()
return
}
```
---
### `usePath(basePath?)`
Returns the current path string. Strips `basePath` if provided (or from context).
```jsx
const path = usePath() // '/users/1'
```
---
### `useFullPath()`
Returns the full path, ignoring any basePath context.
---
### `useBasePath()`
Returns the current basePath from context.
---
### `useHash(options?)`
Returns and watches the URL hash. Options: `{ stripHash?: boolean }` (default `true`).
```jsx
const hash = useHash() // 'section-1' (without '#')
```
---
### `useQueryParams(parseFn?, serializeFn?)`
Returns `[params, setParams]`. `setParams(patch, options?)` merges query string. Options: `{ replace?: boolean }`.
```jsx
const [{ search, page }, setQuery] = useQueryParams()
// Update one key, keep others
setQuery({ search: 'hello' })
// Replace all
setQuery({ page: 2 }, { replace: true })
```
---
### `usePathParams(route | routes[], options?)`
Extract path params from the current path without rendering a route.
```jsx
const { userId } = usePathParams('/users/:userId') // null if no match
```
---
### `useMatch(routes, options?)`
Returns `true`/`false` (or the matched route) without rendering.
---
### `useLocationChange(fn, options?)`
Subscribe to location changes. Options: `{ onInitial?: boolean }`.
The callback receives a `RavigerLocation` object:
```typescript
{
path: string // path with basePath stripped
fullPath: string // full path
search: string // query string
hash: string
href: string
initiatedBy?: 'push' | 'replace' | 'pop'
}
```
```jsx
useLocationChange((loc) => {
analytics.track(loc.path)
}, { onInitial: true })
```
---
### `useHistory()`
Returns history state and whether scroll restoration is enabled.
---
### `useNavigationPrompt(predicate, prompt?)`
Blocks navigation when `predicate` is truthy. Shows browser `confirm()` with `prompt` string.
```jsx
useNavigationPrompt(formIsDirty, 'Leave without saving?')
```
---
### ``
Anchor tag that uses `history.pushState`. All standard anchor props supported. Passes `query` as `NavigateOptions.query`.
```jsx
View User
Search
```
---
### ``
Like `` but applies CSS classes based on path matching.
- `activeClass` — applied when current path starts with href
- `exactActiveClass` — applied when current path exactly matches href
```jsx
Users
```
---
### ``
Immediately navigates to `href` on render. Set `mergeQuery` to carry forward existing query params.
```jsx
```
---
### ``
Provides `basePath` context to all child hooks and `` components. Use for nested routing or sub-apps.
```jsx
```
---
## Nested Routing
Use `basePath` option in `useRoutes` for nested sub-apps. Child hooks and Links automatically inherit the basePath.
```jsx
function App() {
return useRoutes({
'/': () => ,
'/admin/*': () =>
})
}
function AdminApp() {
// basePath '/admin' is set automatically by parent useRoutes
return useRoutes({
'/': () => ,
'/users': () =>
})
}
```
## Common Patterns
**404 / catch-all:**
```jsx
const routes = {
'/': () => ,
'/*': () =>
}
```
**Redirect unauthenticated users:**
```jsx
const routes = {
'/dashboard': () => isLoggedIn ? :
}
```
**Query-driven list filtering:**
```jsx
function UserList() {
const [{ filter = '' }, setQuery] = useQueryParams()
return (
<>
setQuery({ filter: e.target.value })} />
>
)
}
```
**Scroll to hash on navigation:**
```jsx
useLocationChange((loc) => {
if (loc.hash) document.getElementById(loc.hash)?.scrollIntoView()
}, { onInitial: true })
```