CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-router-dom

Declarative routing for React web applications

Pending
Overview
Eval results
Files

route-configuration.mddocs/

Route Configuration

Route definition components and utilities for declaring application routes with support for nested routing, dynamic segments, and route data loading.

Capabilities

Routes

Container component that renders the first route that matches the current location.

/**
 * Container for Route components that renders the first matching route
 * @param props - Routes configuration options
 * @returns Route matching and rendering component
 */
function Routes(props: RoutesProps): JSX.Element;

interface RoutesProps {
  /** Route components to match against */
  children?: React.ReactNode;
  /** Base location for relative matching */
  location?: Partial<Location> | string;
}

Usage Example:

import { Routes, Route } from "react-router-dom";

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/users/:id" element={<UserProfile />} />
    </Routes>
  );
}

Route

Defines a single route with its path, component, and data loading configuration.

/**
 * Defines a route with path matching and element rendering
 * @param props - Route configuration including path and element
 * @returns Route definition for use within Routes
 */
function Route(props: RouteProps): JSX.Element;

interface RouteProps {
  /** URL path pattern to match */
  path?: string;
  /** Indicates this is an index route (matches parent's path exactly) */
  index?: boolean;
  /** React element to render when route matches */
  element?: React.ReactNode;  
  /** Error boundary element for this route */
  errorElement?: React.ReactNode;
  /** Data loader function */
  loader?: LoaderFunction;
  /** Form action handler */
  action?: ActionFunction;
  /** Nested route definitions */
  children?: React.ReactNode;
  /** Enable case-sensitive path matching */
  caseSensitive?: boolean;
  /** Function to determine if route data should revalidate */
  shouldRevalidate?: ShouldRevalidateFunction;
  /** Lazy route component loader */
  lazy?: LazyRouteFunction;
}

type LoaderFunction = (args: LoaderFunctionArgs) => 
  | Promise<Response> 
  | Response 
  | Promise<any> 
  | any;

type ActionFunction = (args: ActionFunctionArgs) => 
  | Promise<Response> 
  | Response 
  | Promise<any> 
  | any;

interface LoaderFunctionArgs {
  /** Request object with URL, headers, and body */
  request: Request;
  /** Route parameters extracted from URL */
  params: Params;
  /** Application context object */
  context?: any;
}

interface ActionFunctionArgs {
  /** Request object with form data and method */
  request: Request;
  /** Route parameters from URL */
  params: Params;
  /** Application context object */
  context?: any;
}

type ShouldRevalidateFunction = (args: ShouldRevalidateFunctionArgs) => boolean;

interface ShouldRevalidateFunctionArgs {
  currentUrl: URL;
  currentParams: Params;
  nextUrl: URL;
  nextParams: Params;
  formMethod?: string;
  formAction?: string;
  formEncType?: string;
  formData?: FormData;
  actionResult?: any;
}

Usage Examples:

// Basic route
<Route path="/users" element={<Users />} />

// Route with parameters
<Route path="/users/:id" element={<UserProfile />} />

// Index route (matches parent exactly)
<Route index element={<Home />} />

// Route with data loading
<Route 
  path="/products/:id" 
  element={<Product />}
  loader={async ({ params }) => {
    return fetch(`/api/products/${params.id}`);
  }}
/>

// Route with form action
<Route 
  path="/contact" 
  element={<ContactForm />}
  action={async ({ request }) => {
    const formData = await request.formData();
    return await submitContact(formData);
  }}
/>

// Nested routes
<Route path="/dashboard" element={<Dashboard />}>
  <Route index element={<DashboardHome />} />
  <Route path="settings" element={<Settings />} />
  <Route path="profile" element={<Profile />} />
</Route>

Outlet

Renders child routes in nested routing scenarios.

/**
 * Renders the matching child route component
 * @param props - Outlet configuration options
 * @returns Child route rendering component
 */
function Outlet(props: OutletProps): JSX.Element;

interface OutletProps {
  /** Context data to pass to child routes */
  context?: unknown;
}

Usage Example:

// Parent component
function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <nav>
        <Link to="stats">Statistics</Link>
        <Link to="settings">Settings</Link>
      </nav>
      {/* Child routes render here */}
      <Outlet />
    </div>
  );
}

// Route configuration
<Route path="/dashboard" element={<Dashboard />}>
  <Route path="stats" element={<Statistics />} />
  <Route path="settings" element={<Settings />} />
</Route>

Await

Component for handling deferred data with Suspense and error boundaries.

/**
 * Component that resolves deferred data with Suspense support
 * @param props - Await component configuration
 * @returns Component that handles async data resolution
 */
function Await<T>(props: AwaitProps<T>): JSX.Element;

interface AwaitProps<T> {
  /** Promise to resolve */
  resolve: Promise<T>;
  /** Component to render when promise resolves */
  children: React.ReactNode | ((value: T) => React.ReactNode);
  /** Component to render when promise rejects */
  errorElement?: React.ReactNode | null;
}

Usage Examples:

import { Await, useLoaderData, defer } from "react-router-dom";
import { Suspense } from "react";

// Loader that returns deferred data
export const userProfileLoader = async ({ params }) => {
  // Fast data loaded immediately
  const basicInfo = await fetch(`/api/users/${params.id}/basic`).then(r => r.json());
  
  // Slow data deferred for streaming
  const postsPromise = fetch(`/api/users/${params.id}/posts`).then(r => r.json());
  const analyticsPromise = fetch(`/api/users/${params.id}/analytics`).then(r => r.json());
  
  return defer({
    basicInfo,
    posts: postsPromise,
    analytics: analyticsPromise
  });
};

// Component using Await for deferred data
function UserProfile() {
  const { basicInfo, posts, analytics } = useLoaderData<{
    basicInfo: User;
    posts: Promise<Post[]>;
    analytics: Promise<Analytics>;
  }>();
  
  return (
    <div>
      {/* Immediate data */}
      <h1>{basicInfo.name}</h1>
      <p>{basicInfo.email}</p>
      
      {/* Deferred data with loading states */}
      <section>
        <h2>Recent Posts</h2>
        <Suspense fallback={<div>Loading posts...</div>}>
          <Await resolve={posts}>
            <PostsList />
          </Await>
        </Suspense>
      </section>
      
      <section>
        <h2>Analytics</h2>
        <Suspense fallback={<div>Loading analytics...</div>}>
          <Await 
            resolve={analytics}
            errorElement={<div>Failed to load analytics</div>}
          >
            <AnalyticsDashboard />
          </Await>
        </Suspense>
      </section>
    </div>
  );
}

// Component that receives resolved data
function PostsList() {
  const posts = useAsyncValue<Post[]>();
  
  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.excerpt}</p>
        </li>
      ))}
    </ul>
  );
}

// Component with error handling
function AnalyticsDashboard() {
  const analytics = useAsyncValue<Analytics>();
  
  return (
    <div>
      <p>Views: {analytics.views}</p>
      <p>Engagement: {analytics.engagement}%</p>
    </div>
  );
}

// Error boundary for async errors
function AsyncErrorBoundary() {
  const error = useAsyncError();
  
  return (
    <div className="error">
      <h3>Something went wrong</h3>
      <p>{error instanceof Error ? error.message : "Unknown error"}</p>
    </div>
  );
}

Route Objects

Declarative route configuration objects for use with router creation functions.

interface RouteObject {
  /** URL path pattern to match */
  path?: string;
  /** Indicates this is an index route */
  index?: boolean;
  /** Nested route definitions */
  children?: RouteObject[];
  /** Enable case-sensitive matching */
  caseSensitive?: boolean;
  /** Unique route identifier */
  id?: string;
  /** Data loader function */
  loader?: LoaderFunction;
  /** Form action handler */
  action?: ActionFunction;
  /** Component to render */
  element?: React.ReactNode | null;
  /** Error boundary component */
  errorElement?: React.ReactNode | null;
  /** Revalidation control function */
  shouldRevalidate?: ShouldRevalidateFunction;
  /** Lazy component loader */
  lazy?: LazyRouteFunction;
}

interface IndexRouteObject extends Omit<RouteObject, "path" | "children"> {
  index: true;
}

interface NonIndexRouteObject extends RouteObject {
  path: string;
  index?: false;
}

interface DataRouteObject extends RouteObject {
  /** Nested routes with data loading */
  children?: DataRouteObject[];
  /** Required unique identifier */
  id: string;
}

type LazyRouteFunction<T extends RouteObject = RouteObject> = () => Promise<LazyRouteModule<T>>;

interface LazyRouteModule<T extends RouteObject = RouteObject> {
  Component?: React.ComponentType<any> | null;
  element?: React.ReactNode | null;
  errorElement?: React.ReactNode | null;
  loader?: T["loader"];
  action?: T["action"];
  shouldRevalidate?: T["shouldRevalidate"];
}

Usage Example:

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

const routes: RouteObject[] = [
  {
    path: "/",
    element: <Root />,
    errorElement: <ErrorBoundary />,
    loader: rootLoader,
    children: [
      {
        index: true,
        element: <Home />,
      },
      {
        path: "products/:id",
        element: <Product />,
        loader: productLoader,
        action: productAction,
      },
    ],
  },
];

const router = createBrowserRouter(routes);

Route Utilities

Functions for working with routes programmatically.

/**
 * Create route objects from JSX Route elements
 * @param children - JSX Route elements
 * @returns Array of RouteObject definitions
 */
function createRoutesFromElements(children: React.ReactNode): RouteObject[];

/** Alias for createRoutesFromElements */
function createRoutesFromChildren(children: React.ReactNode): RouteObject[];

/**
 * Render matched routes as React elements
 * @param matches - Route matches to render
 * @param parentMatches - Parent route matches for context
 * @returns Rendered route elements
 */
function renderMatches(
  matches: RouteMatch[] | null,
  parentMatches?: RouteMatch[]
): React.ReactElement | null;

interface RouteMatch<ParamKey extends string = string> {
  /** Matched route parameters */
  params: Params<ParamKey>;
  /** Matched pathname */
  pathname: string;
  /** Pattern info used for matching */
  pathnameBase: string;
  /** Route definition */
  route: RouteObject;
}

Route Patterns

Dynamic Segments

// URL parameter
<Route path="/users/:userId" element={<User />} />

// Optional parameter
<Route path="/posts/:postId?" element={<Post />} />

// Multiple parameters
<Route path="/users/:userId/posts/:postId" element={<UserPost />} />

Wildcard Routes

// Catch-all route
<Route path="*" element={<NotFound />} />

// Splat routes (capture remaining path)
<Route path="/files/*" element={<FileBrowser />} />

Index Routes

// Renders at parent's exact path
<Route path="/dashboard" element={<Dashboard />}>
  <Route index element={<DashboardHome />} />
  <Route path="settings" element={<Settings />} />
</Route>

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