You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- A function that will be called when this route's parsed params are being used to build a location. This function should return a valid object of `Record<string, string>` mapping.
> The `skipRouteOnParseError` option is currently **experimental** and may change in future releases.
95
+
96
+
- Type:
97
+
98
+
```tsx
99
+
typeskipRouteOnParseError= {
100
+
params?:boolean
101
+
priority?:number
102
+
}
103
+
```
104
+
105
+
- Optional
106
+
- By default, when a route's `params.parse` function throws an error, the route will match and then show an error state during render. With `skipRouteOnParseError.params` enabled, the router will skip routes whose `params.parse` function throws and continue searching for alternative matching routes.
107
+
- See [Guides > Path Params > Validating path parameters during matching](../../guide/path-params#validating-path-parameters-during-matching) for detailed usage examples.
108
+
109
+
> [!IMPORTANT]
110
+
> **Performance impact**: This option has a **non-negligible performance cost** and should not be used indiscriminately. Routes with `skipRouteOnParseError` are placed on separate branches in the route matching tree instead of sharing nodes with other dynamic routes. This reduces the tree's ability to efficiently narrow down matches and requires testing more route, even for routes that wouldn't match the path structure alone.
Copy file name to clipboardExpand all lines: docs/router/framework/react/guide/path-params.md
+297Lines changed: 297 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -738,6 +738,303 @@ function ShopComponent() {
738
738
739
739
Optional path parameters provide a powerful and flexible foundation for implementing internationalization in your TanStack Router applications. Whether you prefer prefix-based or combined approaches, you can create clean, SEO-friendly URLs while maintaining excellent developer experience and type safety.
740
740
741
+
## Validating Path Parameters During Matching
742
+
743
+
> [!WARNING]
744
+
> The `skipRouteOnParseError` option is currently **experimental** and may change in future releases.
745
+
746
+
> [!IMPORTANT]
747
+
> **Performance cost**: This feature has a **non-negligible performance cost** and should not be used indiscriminately. It creates additional branches in the route matching tree, reducing matching efficiency and requiring more route evaluations. Use it only when you genuinely need type-specific routes at the same path level.
748
+
749
+
By default, TanStack Router matches routes based purely on URL structure. A route with `/$param` will match any value for that parameter, and validation via `params.parse` happens later in the route lifecycle. If validation fails, the route shows an error state.
750
+
751
+
However, sometimes you want routes to match only when parameters meet specific criteria, with the router automatically falling back to alternative routes when validation fails. This is where `skipRouteOnParseError` comes in.
752
+
753
+
### When to Use This Feature
754
+
755
+
Use `skipRouteOnParseError.params` when you need:
756
+
757
+
-**Type-specific routes**: Different routes for UUIDs vs. slugs at the same path (e.g., `/$uuid` and `/$slug`)
758
+
-**Format-specific routes**: Date-formatted paths vs. regular slugs (e.g., `/posts/2024-01-15` vs. `/posts/my-post`)
759
+
-**Numeric vs. string routes**: Different behavior for numeric IDs vs. usernames (e.g., `/users/123` vs. `/users/johndoe`)
760
+
-**Pattern-based routing**: Complex validation patterns where you want automatic fallback to other routes
761
+
762
+
Before using `skipRouteOnParseError.params`, consider whether you can achieve your goals with standard route matching:
763
+
764
+
- Using a static route prefix (e.g., `/id/$id` vs. `/username/$username`)
765
+
- Using a prefix or suffix in the path (e.g., `/user-{$id}` vs. `/$username`)
766
+
767
+
### How It Works
768
+
769
+
The `skipRouteOnParseError` option changes when `params.parse` runs, but not what it does:
770
+
771
+
**Without `skipRouteOnParseError`**:
772
+
773
+
- Route matches based on URL structure alone
774
+
-`params.parse` runs during route lifecycle (after match)
775
+
- Errors from `params.parse` cause error state, showing `errorComponent`
776
+
777
+
**With `skipRouteOnParseError.params`**:
778
+
779
+
- Route matching includes running `params.parse`
780
+
- Errors from `params.parse` cause route to be skipped, continuing to find other matches
781
+
- If no route matches, shows `notFoundComponent`
782
+
783
+
Both modes still use `params.parse` for validation and transformation—the difference is timing and error handling.
784
+
785
+
### Basic Example: Numeric IDs with String Fallback
786
+
787
+
```tsx
788
+
// routes/$id.tsx - Only matches numeric IDs
789
+
exportconst Route =createFileRoute('/$id')({
790
+
params: {
791
+
parse: (params) => {
792
+
const id =parseInt(params.id, 10)
793
+
if (isNaN(id)) thrownewError('ID must be numeric')
794
+
return { id }
795
+
},
796
+
},
797
+
skipRouteOnParseError: { params: true },
798
+
component: UserByIdComponent,
799
+
})
800
+
801
+
function UserByIdComponent() {
802
+
const { id } =Route.useParams() // id is number (from parsed params)
When `skipRouteOnParseError` is used, validated routes are treated as having higher priority than non-validated routes _of the same category_. For example, a validated optional route has higher priority than a non-validated optional route, but lower priority than any dynamic route.
When you have multiple validated routes at the same level, and because `params.parse` can be any arbitrary code, you may have situations where multiple routes could potentially validate successfully. In these cases you can provide a custom priority as a tie-breaker using `skipRouteOnParseError.priority`.
932
+
933
+
Higher numbers mean higher priority, and no priority defaults to 0.
if (params.lang&&!validLangs.includes(params.lang)) {
1021
+
thrownewError('Invalid language code')
1022
+
}
1023
+
return { lang: params.lang||'en' }
1024
+
},
1025
+
},
1026
+
skipRouteOnParseError: { params: true },
1027
+
component: HomeComponent,
1028
+
})
1029
+
```
1030
+
1031
+
Results:
1032
+
1033
+
-`/home` → Matches (optional param skipped, defaults to 'en')
1034
+
-`/en/home` → Matches (validation passes)
1035
+
-`/fr/home` → Matches (validation passes)
1036
+
-`/it/home` → No match (validation fails, 'it' not in valid list)
1037
+
741
1038
## Allowed Characters
742
1039
743
1040
By default, path params are escaped with `encodeURIComponent`. If you want to allow other valid URI characters (e.g. `@` or `+`), you can specify that in your [RouterOptions](../api/router/RouterOptionsType.md#pathparamsallowedcharacters-property).
0 commit comments