Minimalist-friendly ~1.5KB router for React
Different location hook implementations for various routing strategies including browser history, hash-based routing, and memory-based routing for testing and SSR.
Default location strategy using the browser's History API for standard web application routing with full URL path support.
/**
* Default browser location hook using History API
* @param options - Configuration options for SSR and path handling
* @returns Tuple of [currentPath, navigateFunction]
*/
function useBrowserLocation(options?: { ssrPath?: Path }): [Path, typeof navigate];
type BrowserLocationHook = (options?: { ssrPath?: Path }) => [Path, typeof navigate];
/**
* Navigate to a new location using History API
* @param to - Target path or URL
* @param options - Navigation options including replace and state
*/
function navigate<S = any>(
to: string | URL,
options?: { replace?: boolean; state?: S }
): void;Usage Examples:
import { Router } from "wouter";
import { useBrowserLocation } from "wouter/use-browser-location";
// Default browser routing (this is the default)
function App() {
return (
<Router>
<Routes />
</Router>
);
}
// Explicit browser location hook
function AppWithCustomHook() {
return (
<Router hook={useBrowserLocation}>
<Routes />
</Router>
);
}
// Direct navigation
import { navigate } from "wouter/use-browser-location";
function CustomButton() {
const handleClick = () => {
navigate("/dashboard", {
replace: false,
state: { from: "button" }
});
};
return <button onClick={handleClick}>Go to Dashboard</button>;
}Additional hooks for fine-grained access to browser location properties, available from the wouter/use-browser-location import.
/**
* Hook for accessing URL pathname
* @param options - SSR path options
* @returns Current pathname
*/
function usePathname(options?: { ssrPath?: Path }): Path;
/**
* Hook for accessing URL search parameters
* @param options - SSR search options
* @returns Current search string
*/
function useSearch(options?: { ssrSearch?: SearchString }): SearchString;
/**
* Hook for accessing browser history state
* @returns Current history state
*/
function useHistoryState<T = any>(): T;
/**
* Generic hook for subscribing to location property changes
* @param fn - Function to get current value
* @param ssrFn - Function to get SSR value
* @returns Current property value
*/
function useLocationProperty<S extends Primitive>(
fn: () => S,
ssrFn?: () => S
): S;
type BrowserSearchHook = (options?: { ssrSearch?: SearchString }) => SearchString;Import Pattern:
import {
usePathname,
useSearch,
useHistoryState,
useLocationProperty,
navigate
} from "wouter/use-browser-location";Usage Examples:
import {
usePathname,
useSearch,
useHistoryState,
useLocationProperty
} from "wouter/use-browser-location";
function LocationDetails() {
const pathname = usePathname();
const search = useSearch();
const historyState = useHistoryState();
return (
<div>
<p>Pathname: {pathname}</p>
<p>Search: {search}</p>
<p>State: {JSON.stringify(historyState)}</p>
</div>
);
}
function CustomLocationHook() {
// Custom property tracking
const hash = useLocationProperty(
() => location.hash,
() => "" // SSR fallback
);
return <div>Hash: {hash}</div>;
}Location strategy using URL hash for routing, useful for single-page applications that need to support older browsers or static hosting.
/**
* Hash-based location hook using URL hash for routing
* @param options - Configuration options including SSR path
* @returns Tuple of [currentPath, navigateFunction]
*/
function useHashLocation(options?: { ssrPath?: Path }): [Path, typeof navigate];
/**
* Navigate using hash-based routing
* @param to - Target path (will be prefixed with #/)
* @param options - Navigation options
*/
function navigate<S = any>(
to: Path,
options?: { state?: S; replace?: boolean }
): void;The hash location hook also provides a custom href formatter:
/** HREF formatter for hash routing - prefixes paths with # */
useHashLocation.hrefs: (href: string) => string;Usage Examples:
import { Router } from "wouter";
import { useHashLocation } from "wouter/use-hash-location";
// Hash-based routing
function HashApp() {
return (
<Router hook={useHashLocation}>
<Routes />
</Router>
);
}
// Direct hash navigation
import { navigate } from "wouter/use-hash-location";
function HashNavigation() {
const goToPage = (page: string) => {
navigate(`/${page}`, { replace: false });
// URL becomes: http://example.com#/about
};
return (
<div>
<button onClick={() => goToPage("about")}>About</button>
<button onClick={() => goToPage("contact")}>Contact</button>
</div>
);
}
// Custom hook usage
function HashLocationExample() {
const [location, navigate] = useHashLocation();
return (
<div>
<p>Hash location: {location}</p>
<button onClick={() => navigate("/settings")}>
Go to Settings
</button>
</div>
);
}In-memory location strategy for testing, server-side rendering, and controlled routing environments where browser APIs are not available.
/**
* Create an in-memory location hook for testing and SSR
* @param options - Memory location configuration
* @returns Memory location hook object with methods
*/
function memoryLocation(options?: {
path?: Path;
searchPath?: SearchString;
static?: boolean;
record?: false;
}): HookReturnValue;
function memoryLocation(options?: {
path?: Path;
searchPath?: SearchString;
static?: boolean;
record: true;
}): HookReturnValue & StubHistory;
type HookReturnValue = {
/** Location hook function for use with Router */
hook: BaseLocationHook;
/** Search hook for query parameters */
searchHook: BaseSearchHook;
/** Navigation function */
navigate: Navigate;
};
type StubHistory = {
/** Array of visited paths when record=true */
history: Path[];
/** Reset function to return to initial state */
reset: () => void;
};
type Navigate<S = any> = (
to: Path,
options?: { replace?: boolean; state?: S }
) => void;Usage Examples:
import { Router } from "wouter";
import { memoryLocation } from "wouter/memory-location";
// Basic memory routing for testing
function TestApp() {
const memoryHook = memoryLocation({ path: "/test-path" });
return (
<Router hook={memoryHook.hook}>
<Routes />
</Router>
);
}
// Memory routing with history tracking
function TestWithHistory() {
const memoryHook = memoryLocation({
path: "/",
record: true
});
// Navigate programmatically
memoryHook.navigate("/about");
memoryHook.navigate("/contact");
console.log(memoryHook.history); // ["/", "/about", "/contact"]
// Reset to initial state
memoryHook.reset();
console.log(memoryHook.history); // ["/"]
return (
<Router hook={memoryHook.hook}>
<Routes />
</Router>
);
}
// Static routing (navigation disabled)
function StaticApp() {
const staticHook = memoryLocation({
path: "/static-page",
static: true // Navigation calls will be ignored
});
return (
<Router hook={staticHook.hook}>
<Routes />
</Router>
);
}
// Memory routing with search parameters
function MemoryWithSearch() {
const memoryHook = memoryLocation({
path: "/search",
searchPath: "q=react&page=1"
});
return (
<Router
hook={memoryHook.hook}
searchHook={memoryHook.searchHook}
>
<Routes />
</Router>
);
}
// Testing helper
function createTestRouter(initialPath = "/") {
const memoryHook = memoryLocation({
path: initialPath,
record: true
});
const TestRouter = ({ children }: { children: React.ReactNode }) => (
<Router hook={memoryHook.hook}>
{children}
</Router>
);
return {
Router: TestRouter,
navigate: memoryHook.navigate,
history: memoryHook.history,
reset: memoryHook.reset
};
}All location strategies support server-side rendering with static path and search parameter configuration.
Usage Examples:
import { Router } from "wouter";
import { useBrowserLocation } from "wouter/use-browser-location";
import { useHashLocation } from "wouter/use-hash-location";
import { memoryLocation } from "wouter/memory-location";
// SSR with browser location
function SSRBrowserApp({ ssrPath }: { ssrPath: string }) {
return (
<Router
hook={useBrowserLocation}
ssrPath={ssrPath}
ssrSearch="param=value"
>
<Routes />
</Router>
);
}
// SSR with hash location
function SSRHashApp({ ssrPath }: { ssrPath: string }) {
return (
<Router
hook={useHashLocation}
ssrPath={ssrPath}
>
<Routes />
</Router>
);
}
// SSR with memory location
function SSRMemoryApp({ ssrPath }: { ssrPath: string }) {
const memoryHook = memoryLocation({
path: ssrPath,
static: true // Prevent navigation during SSR
});
return (
<Router hook={memoryHook.hook}>
<Routes />
</Router>
);
}type Navigate<S = any> = (
to: Path,
options?: { replace?: boolean; state?: S }
) => void;
type Primitive = string | number | bigint | boolean | null | undefined | symbol;
type HookReturnValue<H extends BaseLocationHook> = ReturnType<H>;
type HookNavigationOptions<H extends BaseLocationHook> =
EmptyInterfaceWhenAnyOrNever<
NonNullable<Parameters<HookReturnValue<H>[1]>[1]>
>;Install with Tessl CLI
npx tessl i tessl/npm-wouter