### Install Wouter
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Install Wouter using npm. For Preact projects, use the specific preact package.
```bash
npm i wouter
```
--------------------------------
### Bun Test Example
Source: https://github.com/molefrog/wouter/blob/v3/CLAUDE.md
A basic test case using Bun's built-in testing framework.
```typescript
import { test, expect } from "bun:test";
test("hello world", () => {
expect(1).toBe(1);
});
```
--------------------------------
### Run Bun Server with Hot Reload
Source: https://github.com/molefrog/wouter/blob/v3/CLAUDE.md
Command to start the Bun server with hot module replacement enabled.
```sh
bun --hot ./index.ts
```
--------------------------------
### Basic Wouter App Example
Source: https://github.com/molefrog/wouter/blob/v3/README.md
A simple demo app demonstrating basic routing with Link, Route, and Switch components. It includes nested routes and parameter extraction.
```jsx
import { Link, Route, Switch } from "wouter";
const App = () => (
<>
Profile
About Us
{/*
Routes below are matched exclusively -
the first matched route gets rendered
*/}
{(params) => <>Hello, {params.name}!>}
{/* Default route in a switch */}
404: No such page!
>
);
```
--------------------------------
### Nested Routing Example
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Illustrates how to use the `nest` prop on Route components to create nested routing contexts, where child routes match relative to the parent path.
```javascript
```
--------------------------------
### Testing Navigation and Redirects with memoryLocation
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Configure `memoryLocation` to record navigation history and use its `navigate` function for external navigation. This example demonstrates testing a redirect.
```jsx
it("performs a redirect", () => {
const { hook, history, navigate } = memoryLocation({
path: "/",
// will store navigation history in `history`
record: true,
});
const { container } = render(
IndexOrders
);
expect(history).toStrictEqual(["/"]);
navigate("/unknown/route");
expect(container.innerHTML).toBe("Orders");
expect(history).toStrictEqual(["/", "/unknown/route", "/orders"]);
});
```
--------------------------------
### Server-Side Rendering with Wouter Router
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Configure Wouter for server-side rendering by wrapping your app with `Router` and providing `ssrPath` and `ssrSearch` props. This example shows how to handle redirects during SSR.
```javascript
import { renderToString } from "react-dom/server";
import { Router } from "wouter";
const handleRequest = (req, res) => {
// top-level Router is mandatory in SSR mode
// pass an optional context object to handle redirects on the server
const ssrContext = {};
const prerendered = renderToString(
);
if (ssrContext.redirectTo) {
// encountered redirect
res.redirect(ssrContext.redirectTo);
} else {
// respond with prerendered html
}
};
```
--------------------------------
### Custom Router Configuration with useHashLocation
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Configure Wouter's routing behavior with the Router component. This example demonstrates using a custom hook, useHashLocation, for hash-based routing and setting a base path.
```jsx
import { useHashLocation } from "wouter/use-hash-location";
{/* Your app goes here */}
;
```
--------------------------------
### Customizing Location Hook with Router
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Wrap your application in a `Router` component to customize the location hook. This example shows how to use `useHashLocation` for hash-based routing.
```javascript
import { Router, Route } from "wouter";
import { useHashLocation } from "wouter/use-hash-location";
const App = () => (
...
);
```
--------------------------------
### Exclusive Route Rendering with Switch
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Illustrates how the Switch component renders only the first matching Route, ensuring exclusive routing behavior. Includes an example of a fallback route.
```javascript
import { Route, Switch } from "wouter";
{/*
in wouter, any Route with empty path is considered always active.
This can be used to achieve "default" route behaviour within Switch.
Note: the order matters! See examples below.
*/}
This is rendered when nothing above has matched
```
--------------------------------
### Implement Strict Routes with Custom Parser
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Configure Wouter to enforce strict route matching, including trailing slashes, by providing a custom parser function to the `` component. This example uses `path-to-regexp` to achieve strict routing.
```javascript
import { pathToRegexp } from "path-to-regexp";
/**
* Custom parser based on `pathToRegexp` with strict route option
*/
const strictParser = (path, loose) => {
const keys = [];
const pattern = pathToRegexp(path, keys, { strict: true, end: !loose });
return {
pattern,
// `pathToRegexp` returns some metadata about the keys,
// we want to strip it to just an array of keys
keys: keys.map((k) => k.name),
};
};
const App = () => (
......
);
```
--------------------------------
### Getting Current Location and Navigating with useLocation
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Use `useLocation` to access the current path and a navigation function. The component re-renders when the location changes, and `navigate` updates the path.
```javascript
import { useLocation } from "wouter";
const CurrentLocation = () => {
const [location, navigate] = useLocation();
return (
);
};
```
--------------------------------
### Getting Current Search String with useSearch
Source: https://github.com/molefrog/wouter/blob/v3/README.md
The `useSearch` hook retrieves the current query string without the leading '?'. It triggers a re-render only when the search string itself changes.
```jsx
import { useSearch } from "wouter";
// returns "tab=settings&id=1"
const searchString = useSearch();
```
--------------------------------
### Managing Search Parameters with useSearchParams
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Use `useSearchParams` to get a `URLSearchParams` object and a function to update it. You can update parameters by providing new values, a callback function, or by replacing all parameters.
```jsx
import { useSearchParams } from 'wouter';
const [searchParams, setSearchParams] = useSearchParams();
// extract a specific search parameter
const id = searchParams.get('id');
// modify a specific search parameter
setSearchParams((prev) => {
prev.set('tab', 'settings');
return prev;
});
// override all search parameters
setSearchParams({
id: 1234,
tab: 'settings',
});
// by default, setSearchParams() will push a new history entry
// to avoid this, set `replace` option to `true`
setSearchParams(
(prev) => {
prev.set('order', 'desc');
return prev;
},
{
replace: true,
},
);
// you can also pass a history state in options
setSearchParams(
(prev) => {
prev.set('foo', 'bar');
return prev;
},
{
state: 'hello',
},
);
```
--------------------------------
### Opt-in View Transitions with Link Component
Source: https://github.com/molefrog/wouter/blob/v3/specs/view-transitions-spec.md
Demonstrates how to opt-in to view transitions for specific navigation events using the `transition` prop on the Wouter `` component.
```jsx
// In your component
Home
;
```
--------------------------------
### Opt-in View Transitions Programmatically
Source: https://github.com/molefrog/wouter/blob/v3/specs/view-transitions-spec.md
Shows how to trigger view transitions programmatically by passing the `transition: true` option to Wouter's `navigate` function.
```javascript
const [location, navigate] = useLocation();
navigate("/", { transition: true });
```
--------------------------------
### Using Wouter with Preact
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Shows the import statement difference when using Wouter with Preact, requiring 'wouter-preact' instead of the standard 'wouter' package.
```diff
- import { useRoute, Route, Switch } from "wouter";
+ import { useRoute, Route, Switch } from "wouter-preact";
```
--------------------------------
### Selective View Transitions with Wouter
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Illustrates how to enable View Transitions API selectively for specific links or programmatic navigations using the 'transition' prop within Wouter.
```jsx
// Enable transition for a specific link
About
// Or programmatically
const [location, navigate] = useLocation();
navigate("/about", { transition: true });
// Then check for it in your handler
const aroundNav: AroundNavHandler = (navigate, to, options) => {
if (!document.startViewTransition) {
navigate(to, options);
return;
}
if (options?.transition) {
document.startViewTransition(() => {
flushSync(() => {
navigate(to, options);
});
});
} else {
navigate(to, options);
}
};
```
--------------------------------
### Bun Server with HTML Imports
Source: https://github.com/molefrog/wouter/blob/v3/CLAUDE.md
A Bun server that serves HTML and supports hot module replacement for development. It includes basic routing and optional WebSocket support.
```typescript
import index from "./index.html"
Bun.serve({
routes: {
"/": index,
"/api/users/:id": {
GET: (req) => {
return new Response(JSON.stringify({ id: req.params.id }));
},
},
},
// optional websocket support
websocket: {
open: (ws) => {
ws.send("Hello, world!");
},
message: (ws, message) => {
ws.send(message);
},
close: (ws) => {
// handle close
}
},
development: {
hmr: true,
console: true,
}
})
```
--------------------------------
### Declaring Routes with Different Styles
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Demonstrates three ways to define a Route component: simple form, render-prop style, and using the component prop.
```javascript
import { Route } from "wouter";
// simple form
// render-prop style
{params => }
// the `params` prop will be passed down to
```
--------------------------------
### Integrating Wouter with View Transitions API
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Shows how to integrate Wouter with the View Transitions API by creating a custom aroundNav handler that uses document.startViewTransition and flushSync for synchronous DOM rendering.
```jsx
import { flushSync } from "react-dom";
import { Router, type AroundNavHandler } from "wouter";
const aroundNav: AroundNavHandler = (navigate, to, options) => {
// Check if View Transitions API is supported
if (!document.startViewTransition) {
navigate(to, options);
return;
}
document.startViewTransition(() => {
flushSync(() => {
navigate(to, options);
});
});
};
const App = () => (
{/* Your routes here */}
);
```
--------------------------------
### Using Link with a Custom Component (asChild)
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Demonstrates how to use the `asChild` prop with the Link component to render a custom component that acts as a navigation link. The custom component must implement an `onClick` handler.
```jsx
// use this instead
// Remember, `UIKitLink` must implement an `onClick` handler
// in order for navigation to work!
```
--------------------------------
### Extracting Wildcard Parameters with useRoute
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Demonstrates how to extract parameters from wildcard segments using `useRoute`. The parameter name for wildcards is `"*"`.
```javascript
// wildcards, matches "/app", "/app-1", "/app/home"
const [match, params] = useRoute("/app*");
if (match) {
// "/home" for "/app/home"
const page = params["*"];
}
```
--------------------------------
### Using Bare Location Hooks for Minimalist Routing
Source: https://github.com/molefrog/wouter/blob/v3/README.md
For minimal bundle size, use bare location hooks like `useBrowserLocation`. Manually match the current location to render specific routes.
```js
import { useBrowserLocation } from "wouter/use-browser-location";
const UsersRoute = () => {
const [location] = useBrowserLocation();
if (location !== "/users") return null;
// render the route
};
```
--------------------------------
### Basic HTML Structure
Source: https://github.com/molefrog/wouter/blob/v3/CLAUDE.md
A simple HTML file that imports a JavaScript module for frontend logic.
```html
Hello, world!
```
--------------------------------
### Testing Query Parameters with memoryLocation
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Use `memoryLocation` to test routes with query parameters. Wouter automatically handles `useSearch()` when `memoryLocation` is provided as the hook.
```jsx
it("works with query parameters", () => {
const { hook } = memoryLocation({ path: "/products?sort=price&order=asc" });
const { result } = renderHook(() => useSearch(), {
wrapper: ({ children }) => {children},
});
expect(result.current).toBe("sort=price&order=asc");
});
```
--------------------------------
### useRoute Pattern Cheatsheet
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Illustrates various pattern syntaxes supported by `useRoute`, including named segments, optional parameters, suffixes, wildcards, and regex.
```javascript
useRoute("/app/:page");
useRoute("/app/:page/:section");
// optional parameter, matches "/en/home" and "/home"
useRoute("/:locale?/home");
// suffixes
useRoute("/movies/:title.(mp4|mov)");
// wildcards, matches "/app", "/app-1", "/app/home"
useRoute("/app*");
// optional wildcards, matches "/orders", "/orders/"
// and "/orders/completed/list"
useRoute("/orders/*?");
// regex for matching complex patterns,
// matches "/hello:123"
useRoute(/^[/]([a-z]+):([0-9]+)[/]?$/);
// and with named capture groups
useRoute(/^[/](?[a-z]+):(?[0-9]+)[/]?$/);
```
--------------------------------
### Testing Specific Routes with memoryLocation
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Configure Wouter for testing by using `memoryLocation` to provide a fixture for the current location. The `static` option prevents navigation changes.
```jsx
import { render } from "@testing-library/react";
import { memoryLocation } from "wouter/memory-location";
it("renders a user page", () => {
// `static` option makes it immutable
// even if you call `navigate` somewhere in the app location won't change
const { hook, searchHook } = memoryLocation({ path: "/user/2", static: true });
const { container } = render(
{(params) => <>User ID: {params.id}>}
);
expect(container.innerHTML).toBe("User ID: 2");
});
```
--------------------------------
### Navigating to Absolute Paths with Nested Routes
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Demonstrates using the `~` prefix within a `Link` component to navigate to a top-level absolute path from within a nested routing context.
```javascript
Back to Home
```
--------------------------------
### Create a Default/404 Route with Switch
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Implement a fallback route for 404 Not Found pages by placing a default `` as the last child of a `` component. This route will match if no other routes are satisfied.
```jsx
import { Switch, Route } from "wouter";
...404, Not Found!
```
```jsx
...
{/* will match anything that starts with /users/, e.g. /users/foo, /users/1/edit etc. */}
...
{/* will match everything else */}
{(params) => `404, Sorry the page ${params["*"]} does not exist!`}
```
--------------------------------
### SSR Path and Search Equivalence
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Demonstrates that Wouter can automatically parse search parameters from the `ssrPath` if it contains a '?'.
```jsx
;
// is the same as
;
```
--------------------------------
### Routing Hooks
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Core hooks imported from 'wouter' for routing logic, parameter extraction, and search string access.
```APIDOC
## Routing Hooks
### `useRoute`
#### Description
Determines if the current page matches a given pattern.
### `useLocation`
#### Description
Manipulates the current router's location, subscribing to the browser location by default. This is distinct from `useBrowserLocation`.
### `useParams`
#### Description
Returns an object containing parameters matched from the closest route.
### `useSearch`
#### Description
Returns the search string, which is everything after the '?' in the URL.
### `useRouter`
#### Description
Returns the global router object, useful for advanced configuration and customization. Use only when necessary.
```
--------------------------------
### Specify Base Path for Subfolder Deployment
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Use the `` component to configure a base path when deploying your application to a subfolder. This ensures links and routes are correctly scoped.
```jsx
import { Router, Route, Link } from "wouter";
const App = () => (
{/* the link's href attribute will be "/app/users" */}
Users
The current path is /app/users!
);
```
```jsx
Path is /app/cms/users!
```
--------------------------------
### Basic Link Component Usage
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Shows the basic usage of the Link component for navigation, including its `href` and `to` props, and proxying standard `a` tag attributes.
```javascript
import { Link } from "wouter"
Home
// `to` is an alias for `href`
Home
// all standard `a` props are proxied
Home
// all location hook options are supported
```
--------------------------------
### TypeScript Types for Wouter View Transitions
Source: https://github.com/molefrog/wouter/blob/v3/specs/view-transitions-spec.md
Illustrates the TypeScript types provided by Wouter for view transitions, including `NavigateOptions` which incorporates the `transition` property, and the `AroundNavHandler` type for custom navigation wrappers.
```typescript
import type { NavigateOptions, AroundNavHandler } from "wouter";
// NavigateOptions already includes transition
const navigate = (to: string, options?: NavigateOptions) => {
// options.transition is available
// options.replace is available
// options.state is available
};
// AroundNavHandler type for the aroundNav callback
const aroundNav: AroundNavHandler = (navigate, to, options) => {
if (options?.transition) {
// handle transition
}
navigate(to, options);
};
```
--------------------------------
### Animated Route Transitions with AnimatePresence (Workaround)
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Provides a workaround for animating route transitions with Wouter and framer-motion by using useRoute to conditionally render the animated element as a direct child of AnimatePresence.
```jsx
export const MyComponent = ({ isVisible }) => {
const [isMatch] = useRoute("/");
return (
{isMatch && (
)}
);
};
```
--------------------------------
### Navigation with replace and state options
Source: https://github.com/molefrog/wouter/blob/v3/README.md
The `navigate` function from `useLocation` accepts optional parameters to control navigation behavior. Use `replace: true` to modify the current history entry instead of adding a new one.
```jsx
const [location, navigate] = useLocation();
navigate("/jobs"); // `pushState` is used
navigate("/home", { replace: true }); // `replaceState` is used
```
--------------------------------
### Explicit Arguments for View Transitions Wrapper
Source: https://github.com/molefrog/wouter/blob/v3/specs/view-transitions-spec.md
An alternative implementation for the `aroundNav` function that explicitly defines the `to` and `options` arguments for the navigate function, ensuring compatibility with Wouter's routing.
```javascript
function aroundNav(navigate, to, options) {
if (!document.startViewTransition) {
navigate(to, options);
return;
}
document.startViewTransition(() => {
flushSync(() => {
navigate(to, options);
});
});
}
```
--------------------------------
### Custom Link Wrapper with useRoute Hook
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Create a custom `` wrapper to control additional props like `style` or `aria-current` based on the active route status. It utilizes the `useRoute` hook to determine if the link's `href` matches the current location.
```javascript
const [isActive] = useRoute(props.href);
return (
{props.children}
);
```
--------------------------------
### Styling Active Links with a Function
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Shows how to use a function for the `className` prop on a Link component to dynamically apply styles based on whether the link is active for the current route.
```jsx
(active ? "active" : "")}>Nav
```
--------------------------------
### Granular Control View Transitions Wrapper
Source: https://github.com/molefrog/wouter/blob/v3/specs/view-transitions-spec.md
This `aroundNav` implementation provides granular control, only enabling view transitions when the `options?.transition` flag is explicitly set to true. It includes feature detection and uses `flushSync` for synchronous DOM updates.
```javascript
import { flushSync } from "react-dom";
function aroundNav(navigate, to, options) {
// Feature detection
if (!document.startViewTransition) {
navigate(to, options);
return;
}
// Only use transitions when explicitly requested
if (options?.transition) {
document.startViewTransition(() => {
flushSync(() => {
navigate(to, options);
});
});
} else {
navigate(to, options);
}
}
```
--------------------------------
### Using SSR Search Parameter
Source: https://github.com/molefrog/wouter/blob/v3/README.md
For Server-Side Rendering, pass the `ssrSearch` prop to the `Router` component to provide the initial search string.
```jsx
{/* SSR! */}
```
--------------------------------
### Animated Route Transitions with AnimatePresence (Incorrect Usage)
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Demonstrates an incorrect way to use AnimatePresence with Wouter routes, where the animated element is not a direct child of AnimatePresence.
```jsx
import { motion, AnimatePresence } from "framer-motion";
export const MyComponent = () => (
{/* This will not work! `motion.div` is not a direct child */}
);
```
--------------------------------
### Route Matching with useRoute
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Use `useRoute` to check if the current location matches a pattern and extract parameters. It's powered by `regexparam` for flexible pattern matching.
```javascript
import { useRoute } from "wouter";
const Users = () => {
// `match` is a boolean
const [match, params] = useRoute("/users/:name");
if (match) {
return <>Hello, {params.name}!>;
} else {
return null;
}
};
```
--------------------------------
### Components
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Component-based API elements for building traditional routing interfaces, including links, routes, and switches.
```APIDOC
## Components
### ``
#### Description
Conditionally renders a component based on a provided pattern.
### ``
#### Description
Wraps an `` tag to enable navigation within the application.
### ``
#### Description
Ensures that only the first matched route within its scope is rendered, providing exclusive routing.
### ``
#### Description
When rendered, this component immediately performs a navigation to a specified path.
### ``
#### Description
An optional top-level component used for advanced routing configurations, such as setting base paths or custom match functions.
#### Props
- `hook` (hook): The location hook to use.
- `matcher` (matchFn): A custom matching function.
- `base` (basePath): The base path for routing.
```
--------------------------------
### Programmatic Navigation Outside Components
Source: https://github.com/molefrog/wouter/blob/v3/README.md
Initiate navigation programmatically from outside of React components by importing and using the `navigate` function from `"wouter/use-browser-location"`. This function mirrors the internal navigation logic.
```javascript
import { navigate } from "wouter/use-browser-location";
navigate("/", { replace: true });
```
--------------------------------
### React Frontend Component
Source: https://github.com/molefrog/wouter/blob/v3/CLAUDE.md
A React component that imports CSS and renders a heading. It's designed to be used with Bun's frontend capabilities.
```tsx
import React from "react";
// import .css files directly and it works
import './index.css';
import { createRoot } from "react-dom/client";
const root = createRoot(document.body);
export default function Frontend() {
return