@tanstack/react-router 1.127.9 → 1.128.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2903,6 +2903,262 @@ const link = (
2903
2903
  )
2904
2904
  \`\`\`
2905
2905
 
2906
+ ### Navigating with Optional Parameters
2907
+
2908
+ Optional path parameters provide flexible navigation patterns where you can include or omit parameters as needed. Optional parameters use the \`{-$paramName}\` syntax and offer fine-grained control over URL structure.
2909
+
2910
+ #### Parameter Inheritance vs Removal
2911
+
2912
+ When navigating with optional parameters, you have two main strategies:
2913
+
2914
+ **Inheriting Current Parameters**
2915
+ Use \`params: {}\` to inherit all current route parameters:
2916
+
2917
+ \`\`\`tsx
2918
+ // Inherits current route parameters
2919
+ <Link to="/posts/{-$category}" params={{}}>
2920
+ All Posts
2921
+ </Link>
2922
+ \`\`\`
2923
+
2924
+ **Removing Parameters**
2925
+ Set parameters to \`undefined\` to explicitly remove them:
2926
+
2927
+ \`\`\`tsx
2928
+ // Removes the category parameter
2929
+ <Link to="/posts/{-$category}" params={{ category: undefined }}>
2930
+ All Posts
2931
+ </Link>
2932
+ \`\`\`
2933
+
2934
+ #### Basic Optional Parameter Navigation
2935
+
2936
+ \`\`\`tsx
2937
+ // Navigate with optional parameter
2938
+ <Link
2939
+ to="/posts/{-$category}"
2940
+ params={{ category: 'tech' }}
2941
+ >
2942
+ Tech Posts
2943
+ </Link>
2944
+
2945
+ // Navigate without optional parameter
2946
+ <Link
2947
+ to="/posts/{-$category}"
2948
+ params={{ category: undefined }}
2949
+ >
2950
+ All Posts
2951
+ </Link>
2952
+
2953
+ // Navigate using parameter inheritance
2954
+ <Link
2955
+ to="/posts/{-$category}"
2956
+ params={{}}
2957
+ >
2958
+ Current Category
2959
+ </Link>
2960
+ \`\`\`
2961
+
2962
+ #### Function-Style Parameter Updates
2963
+
2964
+ Function-style parameter updates are particularly useful with optional parameters:
2965
+
2966
+ \`\`\`tsx
2967
+ // Remove a parameter using function syntax
2968
+ <Link
2969
+ to="/posts/{-$category}"
2970
+ params={(prev) => ({ ...prev, category: undefined })}
2971
+ >
2972
+ Clear Category
2973
+ </Link>
2974
+
2975
+ // Update a parameter while keeping others
2976
+ <Link
2977
+ to="/articles/{-$category}/{-$slug}"
2978
+ params={(prev) => ({ ...prev, category: 'news' })}
2979
+ >
2980
+ News Articles
2981
+ </Link>
2982
+
2983
+ // Conditionally set parameters
2984
+ <Link
2985
+ to="/posts/{-$category}"
2986
+ params={(prev) => ({
2987
+ ...prev,
2988
+ category: someCondition ? 'tech' : undefined
2989
+ })}
2990
+ >
2991
+ Conditional Category
2992
+ </Link>
2993
+ \`\`\`
2994
+
2995
+ #### Multiple Optional Parameters
2996
+
2997
+ When working with multiple optional parameters, you can mix and match which ones to include:
2998
+
2999
+ \`\`\`tsx
3000
+ // Navigate with some optional parameters
3001
+ <Link
3002
+ to="/posts/{-$category}/{-$slug}"
3003
+ params={{ category: 'tech', slug: undefined }}
3004
+ >
3005
+ Tech Posts
3006
+ </Link>
3007
+
3008
+ // Remove all optional parameters
3009
+ <Link
3010
+ to="/posts/{-$category}/{-$slug}"
3011
+ params={{ category: undefined, slug: undefined }}
3012
+ >
3013
+ All Posts
3014
+ </Link>
3015
+
3016
+ // Set multiple parameters
3017
+ <Link
3018
+ to="/posts/{-$category}/{-$slug}"
3019
+ params={{ category: 'tech', slug: 'react-tips' }}
3020
+ >
3021
+ Specific Post
3022
+ </Link>
3023
+ \`\`\`
3024
+
3025
+ #### Mixed Required and Optional Parameters
3026
+
3027
+ Optional parameters work seamlessly with required parameters:
3028
+
3029
+ \`\`\`tsx
3030
+ // Required 'id', optional 'tab'
3031
+ <Link
3032
+ to="/users/$id/{-$tab}"
3033
+ params={{ id: '123', tab: 'settings' }}
3034
+ >
3035
+ User Settings
3036
+ </Link>
3037
+
3038
+ // Remove optional parameter while keeping required
3039
+ <Link
3040
+ to="/users/$id/{-$tab}"
3041
+ params={{ id: '123', tab: undefined }}
3042
+ >
3043
+ User Profile
3044
+ </Link>
3045
+
3046
+ // Use function style with mixed parameters
3047
+ <Link
3048
+ to="/users/$id/{-$tab}"
3049
+ params={(prev) => ({ ...prev, tab: 'notifications' })}
3050
+ >
3051
+ User Notifications
3052
+ </Link>
3053
+ \`\`\`
3054
+
3055
+ #### Advanced Optional Parameter Patterns
3056
+
3057
+ **Prefix and Suffix Parameters**
3058
+ Optional parameters with prefix/suffix work with navigation:
3059
+
3060
+ \`\`\`tsx
3061
+ // Navigate to file with optional name
3062
+ <Link
3063
+ to="/files/prefix{-$name}.txt"
3064
+ params={{ name: 'document' }}
3065
+ >
3066
+ Document File
3067
+ </Link>
3068
+
3069
+ // Navigate to file without optional name
3070
+ <Link
3071
+ to="/files/prefix{-$name}.txt"
3072
+ params={{ name: undefined }}
3073
+ >
3074
+ Default File
3075
+ </Link>
3076
+ \`\`\`
3077
+
3078
+ **All Optional Parameters**
3079
+ Routes where all parameters are optional:
3080
+
3081
+ \`\`\`tsx
3082
+ // Navigate to specific date
3083
+ <Link
3084
+ to="/{-$year}/{-$month}/{-$day}"
3085
+ params={{ year: '2023', month: '12', day: '25' }}
3086
+ >
3087
+ Christmas 2023
3088
+ </Link>
3089
+
3090
+ // Navigate to partial date
3091
+ <Link
3092
+ to="/{-$year}/{-$month}/{-$day}"
3093
+ params={{ year: '2023', month: '12', day: undefined }}
3094
+ >
3095
+ December 2023
3096
+ </Link>
3097
+
3098
+ // Navigate to root with all parameters removed
3099
+ <Link
3100
+ to="/{-$year}/{-$month}/{-$day}"
3101
+ params={{ year: undefined, month: undefined, day: undefined }}
3102
+ >
3103
+ Home
3104
+ </Link>
3105
+ \`\`\`
3106
+
3107
+ #### Navigation with Search Params and Optional Parameters
3108
+
3109
+ Optional parameters work great in combination with search params:
3110
+
3111
+ \`\`\`tsx
3112
+ // Combine optional path params with search params
3113
+ <Link
3114
+ to="/posts/{-$category}"
3115
+ params={{ category: 'tech' }}
3116
+ search={{ page: 1, sort: 'newest' }}
3117
+ >
3118
+ Tech Posts - Page 1
3119
+ </Link>
3120
+
3121
+ // Remove path param but keep search params
3122
+ <Link
3123
+ to="/posts/{-$category}"
3124
+ params={{ category: undefined }}
3125
+ search={(prev) => prev}
3126
+ >
3127
+ All Posts - Same Filters
3128
+ </Link>
3129
+ \`\`\`
3130
+
3131
+ #### Imperative Navigation with Optional Parameters
3132
+
3133
+ All the same patterns work with imperative navigation:
3134
+
3135
+ \`\`\`tsx
3136
+ function Component() {
3137
+ const navigate = useNavigate()
3138
+
3139
+ const clearFilters = () => {
3140
+ navigate({
3141
+ to: '/posts/{-$category}/{-$tag}',
3142
+ params: { category: undefined, tag: undefined },
3143
+ })
3144
+ }
3145
+
3146
+ const setCategory = (category: string) => {
3147
+ navigate({
3148
+ to: '/posts/{-$category}/{-$tag}',
3149
+ params: (prev) => ({ ...prev, category }),
3150
+ })
3151
+ }
3152
+
3153
+ const applyFilters = (category?: string, tag?: string) => {
3154
+ navigate({
3155
+ to: '/posts/{-$category}/{-$tag}',
3156
+ params: { category, tag },
3157
+ })
3158
+ }
3159
+ }
3160
+ \`\`\`
3161
+
2906
3162
  ### Active & Inactive Props
2907
3163
 
2908
3164
  The \`Link\` component supports two additional props: \`activeProps\` and \`inactiveProps\`. These props are functions that return additional props for the \`active\` and \`inactive\` states of the link. All props other than styles and classes passed here will override the original props passed to \`Link\`. Any styles or classes passed are merged together.
@@ -3613,6 +3869,219 @@ const router = createRouter({
3613
3869
  The following is the list of accepted allowed characters:
3614
3870
  \`;\` \`:\` \`@\` \`&\` \`=\` \`+\` \`$\` \`,\`
3615
3871
 
3872
+ ## Optional Path Parameters
3873
+
3874
+ Optional path parameters allow you to define route segments that may or may not be present in the URL. They use the \`{-$paramName}\` syntax and provide flexible routing patterns where certain parameters are optional.
3875
+
3876
+ ### Defining Optional Parameters
3877
+
3878
+ Optional path parameters are defined using curly braces with a dash prefix: \`{-$paramName}\`
3879
+
3880
+ \`\`\`tsx
3881
+ // Single optional parameter
3882
+ // src/routes/posts/{-$category}.tsx
3883
+ export const Route = createFileRoute('/posts/{-$category}')({
3884
+ component: PostsComponent,
3885
+ })
3886
+
3887
+ // Multiple optional parameters
3888
+ // src/routes/posts/{-$category}/{-$slug}.tsx
3889
+ export const Route = createFileRoute('/posts/{-$category}/{-$slug}')({
3890
+ component: PostComponent,
3891
+ })
3892
+
3893
+ // Mixed required and optional parameters
3894
+ // src/routes/users/$id/{-$tab}.tsx
3895
+ export const Route = createFileRoute('/users/$id/{-$tab}')({
3896
+ component: UserComponent,
3897
+ })
3898
+ \`\`\`
3899
+
3900
+ ### How Optional Parameters Work
3901
+
3902
+ Optional parameters create flexible URL patterns:
3903
+
3904
+ - \`/posts/{-$category}\` matches both \`/posts\` and \`/posts/tech\`
3905
+ - \`/posts/{-$category}/{-$slug}\` matches \`/posts\`, \`/posts/tech\`, and \`/posts/tech/hello-world\`
3906
+ - \`/users/$id/{-$tab}\` matches \`/users/123\` and \`/users/123/settings\`
3907
+
3908
+ When an optional parameter is not present in the URL, its value will be \`undefined\` in your route handlers and components.
3909
+
3910
+ ### Accessing Optional Parameters
3911
+
3912
+ Optional parameters work exactly like regular parameters in your components, but their values may be \`undefined\`:
3913
+
3914
+ \`\`\`tsx
3915
+ function PostsComponent() {
3916
+ const { category } = Route.useParams()
3917
+
3918
+ return <div>{category ? \`Posts in \${category}\` : 'All Posts'}</div>
3919
+ }
3920
+ \`\`\`
3921
+
3922
+ ### Optional Parameters in Loaders
3923
+
3924
+ Optional parameters are available in loaders and may be \`undefined\`:
3925
+
3926
+ \`\`\`tsx
3927
+ export const Route = createFileRoute('/posts/{-$category}')({
3928
+ loader: async ({ params }) => {
3929
+ // params.category might be undefined
3930
+ return fetchPosts({ category: params.category })
3931
+ },
3932
+ })
3933
+ \`\`\`
3934
+
3935
+ ### Optional Parameters in beforeLoad
3936
+
3937
+ Optional parameters work in \`beforeLoad\` handlers as well:
3938
+
3939
+ \`\`\`tsx
3940
+ export const Route = createFileRoute('/posts/{-$category}')({
3941
+ beforeLoad: async ({ params }) => {
3942
+ if (params.category) {
3943
+ // Validate category exists
3944
+ await validateCategory(params.category)
3945
+ }
3946
+ },
3947
+ })
3948
+ \`\`\`
3949
+
3950
+ ### Advanced Optional Parameter Patterns
3951
+
3952
+ #### With Prefix and Suffix
3953
+
3954
+ Optional parameters support prefix and suffix patterns:
3955
+
3956
+ \`\`\`tsx
3957
+ // File route: /files/prefix{-$name}.txt
3958
+ // Matches: /files/prefix.txt and /files/prefixdocument.txt
3959
+ export const Route = createFileRoute('/files/prefix{-$name}.txt')({
3960
+ component: FileComponent,
3961
+ })
3962
+
3963
+ function FileComponent() {
3964
+ const { name } = Route.useParams()
3965
+ return <div>File: {name || 'default'}</div>
3966
+ }
3967
+ \`\`\`
3968
+
3969
+ #### All Optional Parameters
3970
+
3971
+ You can create routes where all parameters are optional:
3972
+
3973
+ \`\`\`tsx
3974
+ // Route: /{-$year}/{-$month}/{-$day}
3975
+ // Matches: /, /2023, /2023/12, /2023/12/25
3976
+ export const Route = createFileRoute('/{-$year}/{-$month}/{-$day}')({
3977
+ component: DateComponent,
3978
+ })
3979
+
3980
+ function DateComponent() {
3981
+ const { year, month, day } = Route.useParams()
3982
+
3983
+ if (!year) return <div>Select a year</div>
3984
+ if (!month) return <div>Year: {year}</div>
3985
+ if (!day)
3986
+ return (
3987
+ <div>
3988
+ Month: {year}/{month}
3989
+ </div>
3990
+ )
3991
+
3992
+ return (
3993
+ <div>
3994
+ Date: {year}/{month}/{day}
3995
+ </div>
3996
+ )
3997
+ }
3998
+ \`\`\`
3999
+
4000
+ #### Optional Parameters with Wildcards
4001
+
4002
+ Optional parameters can be combined with wildcards for complex routing patterns:
4003
+
4004
+ \`\`\`tsx
4005
+ // Route: /docs/{-$version}/$
4006
+ // Matches: /docs/extra/path, /docs/v2/extra/path
4007
+ export const Route = createFileRoute('/docs/{-$version}/$')({
4008
+ component: DocsComponent,
4009
+ })
4010
+
4011
+ function DocsComponent() {
4012
+ const { version } = Route.useParams()
4013
+ const { _splat } = Route.useParams()
4014
+
4015
+ return (
4016
+ <div>
4017
+ Version: {version || 'latest'}
4018
+ Path: {_splat}
4019
+ </div>
4020
+ )
4021
+ }
4022
+ \`\`\`
4023
+
4024
+ ### Navigating with Optional Parameters
4025
+
4026
+ When navigating to routes with optional parameters, you have fine-grained control over which parameters to include:
4027
+
4028
+ \`\`\`tsx
4029
+ function Navigation() {
4030
+ return (
4031
+ <div>
4032
+ {/* Navigate with optional parameter */}
4033
+ <Link to="/posts/{-$category}" params={{ category: 'tech' }}>
4034
+ Tech Posts
4035
+ </Link>
4036
+
4037
+ {/* Navigate without optional parameter */}
4038
+ <Link to="/posts/{-$category}" params={{ category: undefined }}>
4039
+ All Posts
4040
+ </Link>
4041
+
4042
+ {/* Navigate with multiple optional parameters */}
4043
+ <Link
4044
+ to="/posts/{-$category}/{-$slug}"
4045
+ params={{ category: 'tech', slug: 'react-tips' }}
4046
+ >
4047
+ Specific Post
4048
+ </Link>
4049
+ </div>
4050
+ )
4051
+ }
4052
+ \`\`\`
4053
+
4054
+ ### Type Safety with Optional Parameters
4055
+
4056
+ TypeScript provides full type safety for optional parameters:
4057
+
4058
+ \`\`\`tsx
4059
+ function PostsComponent() {
4060
+ // TypeScript knows category might be undefined
4061
+ const { category } = Route.useParams() // category: string | undefined
4062
+
4063
+ // Safe navigation
4064
+ const categoryUpper = category?.toUpperCase()
4065
+
4066
+ return <div>{categoryUpper || 'All Categories'}</div>
4067
+ }
4068
+
4069
+ // Navigation is type-safe and flexible
4070
+ <Link
4071
+ to="/posts/{-$category}"
4072
+ params={{ category: 'tech' }} // ✅ Valid - string
4073
+ >
4074
+ Tech Posts
4075
+ </Link>
4076
+
4077
+ <Link
4078
+ to="/posts/{-$category}"
4079
+ params={{ category: 123 }} // ✅ Valid - number (auto-stringified)
4080
+ >
4081
+ Category 123
4082
+ </Link>
4083
+ \`\`\`
4084
+
3616
4085
  # Preloading
3617
4086
 
3618
4087
  Preloading in TanStack Router is a way to load a route before the user actually navigates to it. This is useful for routes that are likely to be visited by the user next. For example, if you have a list of posts and the user is likely to click on one of them, you can preload the post route so that it's ready to go when the user clicks on it.