- Spec files
npm-tanstack--react-router
Describes: pkg:npm/@tanstack/react-router@1.132.x
- Description
- Modern and scalable routing for React applications with built-in data fetching, caching, and state management capabilities
- Author
- tessl
- Last updated
How to use
npx @tessl/cli registry install tessl/npm-tanstack--react-router@1.132.0
path-search-utils.md docs/
1# Path & Search Utilities23Low-level utilities for path manipulation, search parameter handling, URL processing, and data validation for robust routing functionality.45## Capabilities67### Path Manipulation89Utilities for working with URL paths, including joining, cleaning, and normalization.1011```typescript { .api }12/**13* Join multiple path segments into a single path14* @param paths - Array of path segments to join15* @returns Combined path string16*/17function joinPaths(paths: Array<string | undefined>): string;1819/**20* Clean and normalize a path21* @param path - Path to clean22* @returns Cleaned path string23*/24function cleanPath(path: string): string;2526/**27* Remove leading and trailing slashes from path28* @param path - Path to trim29* @returns Trimmed path string30*/31function trimPath(path: string): string;3233/**34* Remove leading slashes from path35* @param path - Path to trim36* @returns Path without leading slashes37*/38function trimPathLeft(path: string): string;3940/**41* Remove trailing slashes from path42* @param path - Path to trim43* @returns Path without trailing slashes44*/45function trimPathRight(path: string): string;4647/**48* Resolve a relative path against a base path49* @param basepath - Base path50* @param base - Current base51* @param to - Target path52* @returns Resolved absolute path53*/54function resolvePath(basepath: string, base: string, to: string): string;55```5657**Usage Examples:**5859```typescript60import {61joinPaths,62cleanPath,63trimPath,64trimPathLeft,65trimPathRight,66resolvePath67} from "@tanstack/react-router";6869// Join path segments70const fullPath = joinPaths(["/api", "users", undefined, "123"]);71// Result: "/api/users/123"7273// Clean messy paths74const cleaned = cleanPath("//api///users//123//");75// Result: "/api/users/123"7677// Trim slashes78const trimmed = trimPath("/path/to/resource/");79// Result: "path/to/resource"8081const leftTrimmed = trimPathLeft("///path/to/resource");82// Result: "path/to/resource"8384const rightTrimmed = trimPathRight("path/to/resource///");85// Result: "path/to/resource"8687// Resolve relative paths88const resolved = resolvePath("/app", "/users", "../posts/123");89// Result: "/app/posts/123"9091// Resolve from root92const absolute = resolvePath("", "/users/123", "../../admin");93// Result: "/admin"94```9596### Path Parsing and Interpolation9798Utilities for parsing paths and interpolating parameters.99100```typescript { .api }101/**102* Parse a pathname into segments103* @param pathname - Pathname to parse104* @returns Array of path segments105*/106function parsePathname(pathname: string): Array<string>;107108/**109* Interpolate path parameters into a path template110* @param path - Path template with parameter placeholders111* @param params - Parameters to interpolate112* @returns Path with parameters filled in113*/114function interpolatePath(path: string, params: Record<string, any>): string;115```116117**Usage Examples:**118119```typescript120import { parsePathname, interpolatePath } from "@tanstack/react-router";121122// Parse pathname into segments123const segments = parsePathname("/users/123/posts/456");124// Result: ["users", "123", "posts", "456"]125126const rootSegments = parsePathname("/");127// Result: []128129// Interpolate parameters130const userPath = interpolatePath("/users/$userId/posts/$postId", {131userId: "123",132postId: "456",133});134// Result: "/users/123/posts/456"135136// With optional parameters137const profilePath = interpolatePath("/profile/$userId?", {138userId: undefined,139});140// Result: "/profile"141142// Complex interpolation143const complexPath = interpolatePath(144"/org/$orgId/project/$projectId/task/$taskId",145{146orgId: "acme",147projectId: "website",148taskId: "fix-bug-123",149}150);151// Result: "/org/acme/project/website/task/fix-bug-123"152```153154### Search Parameter Processing155156Utilities for parsing, stringifying, and manipulating URL search parameters.157158```typescript { .api }159/**160* Default search parameter parser161* @param searchStr - Search string to parse162* @returns Parsed search object163*/164function defaultParseSearch(searchStr: string): Record<string, any>;165166/**167* Default search parameter stringifier168* @param search - Search object to stringify169* @returns URL search string170*/171function defaultStringifySearch(search: Record<string, any>): string;172173/**174* Create a custom search parser175* @param parser - Custom parser function176* @returns Search parser function177*/178function parseSearchWith<T>(179parser: (searchStr: string) => T180): (searchStr: string) => T;181182/**183* Create a custom search stringifier184* @param stringify - Custom stringify function185* @returns Search stringifier function186*/187function stringifySearchWith<T>(188stringify: (search: T) => string189): (search: T) => string;190191type SearchParser<T = any> = (searchStr: string) => T;192type SearchSerializer<T = any> = (search: T) => string;193```194195**Usage Examples:**196197```typescript198import {199defaultParseSearch,200defaultStringifySearch,201parseSearchWith,202stringifySearchWith203} from "@tanstack/react-router";204205// Default parsing and stringifying206const searchObj = defaultParseSearch("?name=john&age=25&active=true");207// Result: { name: "john", age: "25", active: "true" }208209const searchStr = defaultStringifySearch({210name: "jane",211age: 30,212tags: ["dev", "react"],213});214// Result: "name=jane&age=30&tags=dev&tags=react"215216// Custom parser with type conversion217const typedParser = parseSearchWith((searchStr: string) => {218const params = new URLSearchParams(searchStr);219return {220page: Number(params.get("page")) || 1,221limit: Number(params.get("limit")) || 10,222sort: params.get("sort") || "created_at",223desc: params.get("desc") === "true",224tags: params.getAll("tags"),225};226});227228const parsed = typedParser("?page=2&limit=20&desc=true&tags=react&tags=routing");229// Result: { page: 2, limit: 20, sort: "created_at", desc: true, tags: ["react", "routing"] }230231// Custom stringifier232const typedStringifier = stringifySearchWith((search: {233page: number;234limit: number;235filters?: Record<string, any>;236}) => {237const params = new URLSearchParams();238params.set("page", search.page.toString());239params.set("limit", search.limit.toString());240241if (search.filters) {242Object.entries(search.filters).forEach(([key, value]) => {243if (Array.isArray(value)) {244value.forEach(v => params.append(key, String(v)));245} else {246params.set(key, String(value));247}248});249}250251return params.toString();252});253```254255### Search Parameter Filtering256257Utilities for filtering and manipulating search parameters.258259```typescript { .api }260/**261* Retain only specific search parameters262* @param search - Search object to filter263* @param retain - Array of keys to retain264* @returns Filtered search object265*/266function retainSearchParams<T>(267search: T,268retain: Array<string | number>269): Partial<T>;270271/**272* Remove specific search parameters273* @param search - Search object to filter274* @param strip - Array of keys to remove275* @returns Filtered search object276*/277function stripSearchParams<T>(278search: T,279strip: Array<string | number>280): Partial<T>;281```282283**Usage Examples:**284285```typescript286import { retainSearchParams, stripSearchParams } from "@tanstack/react-router";287288const searchParams = {289page: 1,290limit: 10,291sort: "name",292filter: "active",293debug: true,294internal: "secret",295};296297// Retain only specific params298const publicParams = retainSearchParams(searchParams, ["page", "limit", "sort", "filter"]);299// Result: { page: 1, limit: 10, sort: "name", filter: "active" }300301// Strip sensitive params302const cleanParams = stripSearchParams(searchParams, ["debug", "internal"]);303// Result: { page: 1, limit: 10, sort: "name", filter: "active" }304305// Use in navigation306function NavigateWithCleanParams() {307const currentSearch = useSearch();308const navigate = useNavigate();309310const navigateToNextPage = () => {311const cleanSearch = stripSearchParams(currentSearch, ["debug", "internal"]);312navigate({313search: {314...cleanSearch,315page: (cleanSearch.page || 1) + 1,316},317});318};319320return <button onClick={navigateToNextPage}>Next Page</button>;321}322```323324### Deep Comparison Utilities325326Utilities for deep equality checking and structural sharing.327328```typescript { .api }329/**330* Deep equality comparison331* @param a - First value to compare332* @param b - Second value to compare333* @param opts - Comparison options334* @returns Whether values are deeply equal335*/336function deepEqual(337a: any,338b: any,339opts?: {340partial?: boolean;341ignoreUndefined?: boolean;342}343): boolean;344345/**346* Deep equality replacement for structural sharing347* @param prev - Previous value348* @param next - Next value349* @returns Previous value if equal, next value if different350*/351function replaceEqualDeep<T>(prev: T, next: T): T;352353/**354* Check if value is a plain object355* @param obj - Value to check356* @returns Whether value is a plain object357*/358function isPlainObject(obj: any): boolean;359360/**361* Check if value is a plain array362* @param obj - Value to check363* @returns Whether value is a plain array364*/365function isPlainArray(obj: any): boolean;366```367368**Usage Examples:**369370```typescript371import {372deepEqual,373replaceEqualDeep,374isPlainObject,375isPlainArray376} from "@tanstack/react-router";377378// Deep equality comparison379const obj1 = { a: 1, b: { c: 2, d: [3, 4] } };380const obj2 = { a: 1, b: { c: 2, d: [3, 4] } };381const obj3 = { a: 1, b: { c: 2, d: [3, 5] } };382383console.log(deepEqual(obj1, obj2)); // true384console.log(deepEqual(obj1, obj3)); // false385386// Partial comparison387const partial = { a: 1, b: { c: 2 } };388const full = { a: 1, b: { c: 2, d: 3 }, e: 4 };389console.log(deepEqual(partial, full, { partial: true })); // true390391// Structural sharing for performance392const prevState = { users: [1, 2, 3], posts: [4, 5, 6] };393const nextState = { users: [1, 2, 3], posts: [4, 5, 7] };394395const optimized = replaceEqualDeep(prevState, nextState);396// optimized.users === prevState.users (same reference)397// optimized.posts !== prevState.posts (different reference)398399// Type checking400console.log(isPlainObject({})); // true401console.log(isPlainObject([])); // false402console.log(isPlainObject(new Date())); // false403404console.log(isPlainArray([])); // true405console.log(isPlainArray({})); // false406console.log(isPlainArray("string")); // false407```408409### Functional Update Utilities410411Utilities for applying functional updates to data.412413```typescript { .api }414/**415* Apply a functional update to a value416* @param updater - Update function or new value417* @param previous - Previous value418* @returns Updated value419*/420function functionalUpdate<T>(421updater: T | ((prev: T) => T),422previous: T423): T;424```425426**Usage Examples:**427428```typescript429import { functionalUpdate } from "@tanstack/react-router";430431// Simple value update432const newValue = functionalUpdate("new", "old");433// Result: "new"434435// Functional update436const newObj = functionalUpdate(437(prev) => ({ ...prev, updated: true }),438{ id: 1, name: "test" }439);440// Result: { id: 1, name: "test", updated: true }441442// Use in search parameter updates443function SearchUpdater() {444const search = useSearch();445const navigate = useNavigate();446447const updateSearch = (updater: (prev: any) => any) => {448const newSearch = functionalUpdate(updater, search);449navigate({ search: newSearch });450};451452return (453<div>454<button455onClick={() =>456updateSearch((prev) => ({ ...prev, page: (prev.page || 1) + 1 }))457}458>459Next Page460</button>461<button462onClick={() =>463updateSearch((prev) => ({ ...prev, sort: prev.sort === "asc" ? "desc" : "asc" }))464}465>466Toggle Sort467</button>468</div>469);470}471```472473### URL Construction Utilities474475Utilities for constructing and manipulating URLs.476477```typescript { .api }478/**479* Root route identifier constant480*/481const rootRouteId: "__root__";482483/**484* Check if value matches a route match object485* @param obj - Object to check486* @returns Whether object is a route match487*/488function isMatch(obj: any): obj is RouteMatch;489```490491**Usage Examples:**492493```typescript494import { rootRouteId, isMatch } from "@tanstack/react-router";495496// Root route identification497const isRootRoute = (routeId: string) => routeId === rootRouteId;498499// Route match type checking500function processMatches(matches: unknown[]) {501const validMatches = matches.filter(isMatch);502503return validMatches.map(match => ({504id: match.id,505pathname: match.pathname,506params: match.params,507}));508}509510// Use in route tree construction511const routeTree = rootRoute.addChildren([512homeRoute,513aboutRoute,514postsRoute.addChildren([515postDetailRoute,516newPostRoute,517]),518]);519```520521### Route Rendering Utilities522523Utilities for handling route rendering, particularly for not found scenarios.524525```typescript { .api }526/**527* Renders the appropriate not found component for a route528* @param router - Router instance529* @param route - Route that triggered not found530* @param data - Optional data to pass to not found component531* @returns JSX element with not found component532*/533function renderRouteNotFound(534router: AnyRouter,535route: AnyRoute,536data: any537): JSX.Element;538```539540**Usage Examples:**541542```typescript543import { renderRouteNotFound } from "@tanstack/react-router";544545// Manual not found rendering (typically handled internally)546function CustomRouteRenderer({ router, route, error }: {547router: AnyRouter;548route: AnyRoute;549error: any;550}) {551// Handle not found scenarios552if (error?.status === 404) {553return renderRouteNotFound(router, route, error);554}555556// Handle other rendering scenarios557return <route.component />;558}559```560561## Types562563### Path Types564565```typescript { .api }566type Segment = string;567568type RemoveTrailingSlashes<T extends string> = T extends `${infer R}/`569? RemoveTrailingSlashes<R>570: T;571572type RemoveLeadingSlashes<T extends string> = T extends `/${infer R}`573? RemoveLeadingSlashes<R>574: T;575576type TrimPath<T extends string> = RemoveTrailingSlashes<RemoveLeadingSlashes<T>>;577type TrimPathLeft<T extends string> = RemoveLeadingSlashes<T>;578type TrimPathRight<T extends string> = RemoveTrailingSlashes<T>;579```580581### Search Types582583```typescript { .api }584interface SearchFilter {585key: string;586value: any;587operator: "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "contains";588}589590type SearchSchemaInput = Record<string, any>;591592interface ParsedLocation {593pathname: string;594search: Record<string, any>;595searchStr: string;596hash: string;597href: string;598state?: any;599}600```601602### Utility Types603604```typescript { .api }605type Constrain<T, U> = T extends U ? T : U;606607type Expand<T> = T extends (...args: infer A) => infer R608? (...args: Expand<A>) => Expand<R>609: T extends object610? T extends infer O611? { [K in keyof O]: Expand<O[K]> }612: never613: T;614615type Assign<T, U> = {616[K in keyof T]: K extends keyof U ? U[K] : T[K];617} & {618[K in keyof U]: U[K];619};620621type MergeAll<T extends readonly unknown[]> = T extends readonly [622infer H,623...infer Tail624]625? H & MergeAll<Tail>626: {};627628type IntersectAssign<T, U> = T & U;629```