CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-router-dom

Declarative routing for React web applications

Pending
Overview
Eval results
Files

router-creation.mddocs/

Router Creation

Functions for creating router instances programmatically with support for data loading, static generation, and memory-based routing for testing.

Capabilities

createBrowserRouter

Creates a browser router instance with data loading capabilities.

/**
 * Creates a browser router with HTML5 history and data loading
 * @param routes - Array of route definitions
 * @param opts - Router configuration options
 * @returns DataRouter instance with full feature support
 */
function createBrowserRouter(
  routes: RouteObject[],
  opts?: DOMRouterOpts
): DataRouter;

interface DOMRouterOpts {
  /** Base URL for all routes */
  basename?: string;
  /** Custom data loading strategy */
  unstable_dataStrategy?: DataStrategyFunction;
  /** Dynamic route loading function */
  unstable_patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction;
  /** Future flags for experimental features */
  future?: Partial<Future>;
  /** Window object to use (for testing) */
  window?: Window;
}

interface DataRouter {
  /** Initialize the router and start listening */
  initialize(): void;
  /** Subscribe to router state changes */
  subscribe(fn: RouterSubscriber): () => void;
  /** Navigate programmatically */
  navigate(to: To, opts?: RouterNavigateOptions): Promise<void>;
  /** Fetch data for a route */
  fetch(key: string, routeId: string, href: string, opts?: RouterFetchOptions): Promise<void>;
  /** Trigger data revalidation */
  revalidate(): void;
  /** Get data for a specific route */
  getRouteData(routeId: string): any;
  /** Clean up and dispose router */
  dispose(): void;
  /** Current router state */
  state: RouterState;
}

Usage Examples:

import { createBrowserRouter, RouterProvider } from "react-router-dom";

// Basic router setup
const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    children: [
      {
        path: "dashboard",
        element: <Dashboard />,
        loader: async () => {
          const response = await fetch("/api/dashboard");
          return response.json();
        },
      },
      {
        path: "users/:id",
        element: <User />,
        loader: async ({ params }) => {
          const response = await fetch(`/api/users/${params.id}`);
          return response.json();
        },
        action: async ({ request, params }) => {
          const formData = await request.formData();
          const response = await fetch(`/api/users/${params.id}`, {
            method: "PUT",
            body: formData,
          });
          return response.json();
        },
      },
    ],
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

// Router with options
const router = createBrowserRouter(routes, {
  basename: "/my-app",
  future: {
    unstable_middleware: true,
  },
});

createHashRouter

Creates a hash-based router for compatibility with older browsers and static hosting.

/**
 * Creates a hash router for static hosting and legacy browser support
 * @param routes - Array of route definitions
 * @param opts - Router configuration options
 * @returns DataRouter instance using hash-based routing
 */
function createHashRouter(
  routes: RouteObject[],
  opts?: DOMRouterOpts
): DataRouter;

Usage Example:

import { createHashRouter, RouterProvider } from "react-router-dom";

const router = createHashRouter([
  {
    path: "/",
    element: <Home />,
  },
  {
    path: "/about",
    element: <About />,
  },
]);

// URLs will be: example.com#/ and example.com#/about
function App() {
  return <RouterProvider router={router} />;
}

createMemoryRouter

Creates an in-memory router perfect for testing and non-browser environments.

/**
 * Creates a memory router that stores history in memory
 * @param routes - Array of route definitions
 * @param opts - Memory router configuration options
 * @returns DataRouter instance with in-memory history
 */
function createMemoryRouter(
  routes: RouteObject[],
  opts?: MemoryRouterOpts
): DataRouter;

interface MemoryRouterOpts {
  /** Base URL for all routes */
  basename?: string;
  /** Custom data loading strategy */
  unstable_dataStrategy?: DataStrategyFunction;
  /** Dynamic route loading function */
  unstable_patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction;
  /** Future flags */
  future?: Partial<Future>;
  /** Initial location entries */
  initialEntries?: InitialEntry[];
  /** Initial index in history stack */
  initialIndex?: number;
}

type InitialEntry = string | Partial<Location>;

Usage Examples:

import { createMemoryRouter, RouterProvider } from "react-router-dom";

// Testing setup
const router = createMemoryRouter(
  [
    {
      path: "/",
      element: <Home />,
    },
    {
      path: "/users/:id",
      element: <User />,
      loader: ({ params }) => ({ id: params.id, name: "John" }),
    },
  ],
  {
    initialEntries: ["/", "/users/123"],
    initialIndex: 1, // Start at /users/123
  }
);

// Test component
function TestApp() {
  return <RouterProvider router={router} />;
}

// React Native or Node.js usage
const serverRouter = createMemoryRouter(routes, {
  initialEntries: [request.url],
});

createStaticRouter

Creates a static router for server-side rendering.

/**
 * Creates a static router for server-side rendering
 * @param routes - Array of route definitions
 * @param location - Request location information
 * @param opts - Static router options
 * @returns DataRouter instance for SSR
 */
function createStaticRouter(
  routes: RouteObject[],
  location: Partial<Location> | string,
  opts?: {
    basename?: string;
    future?: Partial<Future>;
  }
): DataRouter;

Usage Example:

import { createStaticRouter, StaticRouterProvider } from "react-router-dom";

// Server-side rendering
export async function render(request: Request) {
  const router = createStaticRouter(routes, request.url);
  
  const html = ReactDOMServer.renderToString(
    <StaticRouterProvider router={router} context={{}} />
  );
  
  return new Response(html, {
    headers: { "Content-Type": "text/html" },
  });
}

createStaticHandler

Creates a static handler for data loading in SSR environments.

/**
 * Creates a static handler for server-side data loading
 * @param routes - Array of route definitions
 * @param opts - Handler configuration options
 * @returns StaticHandler for processing requests
 */
function createStaticHandler(
  routes: RouteObject[],
  opts?: {
    basename?: string;
    unstable_dataStrategy?: DataStrategyFunction;
  }
): StaticHandler;

interface StaticHandler {
  /** Handle a request and return data/redirect */
  query(request: Request, opts?: {
    requestContext?: unknown;
    unstable_dataStrategy?: DataStrategyFunction;
  }): Promise<StaticHandlerContext | Response>;
  
  /** Handle a data request */
  queryRoute(request: Request, opts?: {
    routeId: string;
    requestContext?: unknown;
  }): Promise<any>;
}

interface StaticHandlerContext {
  basename: string;
  location: Location;
  matches: StaticHandlerMatch[];
  loaderData: Record<string, any>;
  actionData: Record<string, any> | null;
  errors: Record<string, any> | null;
  statusCode: number;
  loaderHeaders: Record<string, Headers>;
  actionHeaders: Record<string, Headers> | null;
  activeDeferreds: Record<string, DeferredData> | null;
}

Usage Example:

import { createStaticHandler, createStaticRouter } from "react-router-dom";

// Server setup
const routes = [
  {
    path: "/",
    element: <Home />,
    loader: () => ({ message: "Welcome!" }),
  },
  {
    path: "/users/:id",
    element: <User />,
    loader: async ({ params }) => {
      const user = await fetchUser(params.id);
      return { user };
    },
  },
];

export async function handleRequest(request: Request) {
  const handler = createStaticHandler(routes);
  const context = await handler.query(request);
  
  if (context instanceof Response) {
    return context; // Redirect response
  }
  
  const router = createStaticRouter(routes, context.location);
  
  const html = ReactDOMServer.renderToString(
    <StaticRouterProvider router={router} context={context} />
  );
  
  return new Response(html, {
    status: context.statusCode,
    headers: { "Content-Type": "text/html" },
  });
}

Router Configuration Options

Data Strategy

Custom data loading strategy for advanced use cases.

type DataStrategyFunction = (args: DataStrategyFunctionArgs) => Promise<DataStrategyResult>;

interface DataStrategyFunctionArgs {
  request: Request;
  matches: DataStrategyMatch[];
}

interface DataStrategyMatch {
  route: RouteObject;
  params: Params;
  shouldLoad: boolean;
  resolve: (value: any) => void;
  reject: (error: any) => void;
}

interface DataStrategyResult {
  [routeId: string]: any;
}

Dynamic Route Loading

Function for loading routes dynamically during navigation.

type PatchRoutesOnNavigationFunction = (
  args: PatchRoutesOnNavigationFunctionArgs
) => Promise<void> | void;

interface PatchRoutesOnNavigationFunctionArgs {
  path: string;
  matches: RouteMatch[];
  patch: (routeId: string | null, children: RouteObject[]) => void;
}

Future Flags

Configuration for experimental features.

interface Future {
  /** Enable middleware support */
  unstable_middleware: boolean;
  /** Enable lazy route discovery */
  unstable_lazyRouteDiscovery: boolean;
  /** Enable optimistic UI updates */
  unstable_optimisticUI: boolean;
}

Router Selection Guide

  • createBrowserRouter: Modern web applications with clean URLs and data loading
  • createHashRouter: Static hosting, legacy browsers, or when clean URLs aren't available
  • createMemoryRouter: Testing, React Native, or server-side environments
  • createStaticRouter: Server-side rendering with React frameworks
  • createStaticHandler: Advanced SSR with custom data loading strategies

Best Practices

Route Definition

// Organize routes hierarchically
const routes = [
  {
    path: "/",
    element: <Root />,
    errorElement: <ErrorBoundary />,
    loader: rootLoader,
    children: [
      { index: true, element: <Home /> },
      {
        path: "dashboard",
        element: <Dashboard />,
        loader: dashboardLoader,
        children: [
          { path: "analytics", element: <Analytics /> },
          { path: "settings", element: <Settings /> },
        ],
      },
    ],
  },
];

Error Handling

// Add error boundaries at appropriate levels
const routes = [
  {
    path: "/",
    element: <Root />,
    errorElement: <RootErrorBoundary />,
    children: [
      {
        path: "admin",
        element: <Admin />,
        errorElement: <AdminErrorBoundary />,
        loader: adminLoader,
      },
    ],
  },
];

Data Loading

// Implement proper error handling in loaders
const userLoader = async ({ params }) => {
  try {
    const response = await fetch(`/api/users/${params.id}`);
    if (!response.ok) {
      throw new Response("User not found", { status: 404 });
    }
    return response.json();
  } catch (error) {
    throw new Response("Network error", { status: 500 });
  }
};

Install with Tessl CLI

npx tessl i tessl/npm-react-router-dom

docs

data-loading-hooks.md

index.md

navigation-components.md

navigation-hooks.md

route-configuration.md

router-components.md

router-creation.md

server-side-rendering.md

utilities.md

tile.json