CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wouter

Minimalist-friendly ~1.5KB router for React

Overview
Eval results
Files

location-strategies.mddocs/

Location Strategies

Different location hook implementations for various routing strategies including browser history, hash-based routing, and memory-based routing for testing and SSR.

Capabilities

Browser Location Hook

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>;
}

Browser Location Utilities

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>;
}

Hash Location Hook

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>
  );
}

Memory Location Hook

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
  };
}

Server-Side Rendering

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>
  );
}

Types

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

docs

hooks.md

index.md

location-strategies.md

routing-components.md

tile.json