@tanstack/react-router 1.160.0 → 1.161.1
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.
- package/dist/cjs/Asset.cjs +33 -19
- package/dist/cjs/Asset.cjs.map +1 -1
- package/dist/cjs/link.cjs +13 -5
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/esm/Asset.js +33 -19
- package/dist/esm/Asset.js.map +1 -1
- package/dist/esm/link.js +13 -5
- package/dist/esm/link.js.map +1 -1
- package/dist/llms/rules/guide.d.ts +1 -1
- package/dist/llms/rules/guide.js +2821 -253
- package/dist/llms/rules/installation.d.ts +1 -1
- package/dist/llms/rules/installation.js +376 -357
- package/dist/llms/rules/routing.d.ts +1 -1
- package/dist/llms/rules/routing.js +436 -31
- package/dist/llms/rules/setup-and-architecture.d.ts +1 -1
- package/dist/llms/rules/setup-and-architecture.js +253 -90
- package/package.json +2 -2
- package/src/Asset.tsx +45 -17
- package/src/link.tsx +18 -9
|
@@ -144,32 +144,22 @@ Enough overview, there's so much more to do with TanStack Router. Hit that next
|
|
|
144
144
|
|
|
145
145
|
The fastest way to get started with TanStack Router is to scaffold a new project. Just run:
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
<!-- ::start:tabs variant="package-managers" mode="local-install" -->
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
\`\`\`
|
|
149
|
+
react: create-tsrouter-app@latest
|
|
150
|
+
solid: create-tsrouter-app@latest --framework solid
|
|
152
151
|
|
|
153
|
-
|
|
152
|
+
<!-- ::end:tabs -->
|
|
154
153
|
|
|
155
154
|
The CLI will guide you through a short series of prompts to customize your setup, including options for:
|
|
156
155
|
|
|
157
|
-
[//]: # 'CLIPrompts'
|
|
158
|
-
|
|
159
156
|
- File-based or code-based route configuration
|
|
160
157
|
- TypeScript support
|
|
161
158
|
- Tailwind CSS integration
|
|
162
159
|
- Toolchain setup
|
|
163
160
|
- Git initialization
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
Once complete, a new React project will be generated with TanStack Router installed and ready to use:
|
|
168
|
-
|
|
169
|
-
\`\`\`sh
|
|
170
|
-
cd your-project-name
|
|
171
|
-
npm run dev
|
|
172
|
-
\`\`\`
|
|
162
|
+
Once complete, a new project will be generated with TanStack Router installed and ready to use.
|
|
173
163
|
|
|
174
164
|
> [!TIP]
|
|
175
165
|
> For full details on available options and templates, visit the [\`create-tsrouter-app\` documentation](https://github.com/TanStack/create-tsrouter-app/tree/main/cli/create-tsrouter-app).
|
|
@@ -182,32 +172,25 @@ TanStack Router supports both file-based and code-based route configurations. Yo
|
|
|
182
172
|
|
|
183
173
|
The file-based approach is the recommended option for most projects. It automatically creates routes based on your file structure, giving you the best mix of performance, simplicity, and developer experience.
|
|
184
174
|
|
|
185
|
-
|
|
175
|
+
<!-- ::start:tabs variant="package-manager" mode="local-install" -->
|
|
186
176
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
\`\`\`
|
|
177
|
+
react: create-tsrouter-app@latest my-app --template file-router
|
|
178
|
+
solid: create-tsrouter-app@latest my-app --framework solid --template file-router
|
|
190
179
|
|
|
191
|
-
|
|
180
|
+
<!-- ::end:tabs -->
|
|
192
181
|
|
|
193
182
|
### Code-Based Route Configuration
|
|
194
183
|
|
|
195
184
|
If you prefer to define routes programmatically, you can use the code-based route configuration. This approach gives you full control over routing logic.
|
|
196
185
|
|
|
197
|
-
|
|
186
|
+
<!-- ::start:tabs variant="package-manager" mode="local-install" -->
|
|
198
187
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
\`\`\`
|
|
202
|
-
|
|
203
|
-
[//]: # 'createAppCommandCodeBased'
|
|
188
|
+
react: create-tsrouter-app@latest my-app
|
|
189
|
+
solid: create-tsrouter-app@latest my-app --framework solid
|
|
204
190
|
|
|
205
|
-
|
|
191
|
+
<!-- ::end:tabs -->
|
|
206
192
|
|
|
207
|
-
|
|
208
|
-
cd my-app
|
|
209
|
-
npm run dev
|
|
210
|
-
\`\`\`
|
|
193
|
+
With either approach, navigate to your project directory and start the development server.
|
|
211
194
|
|
|
212
195
|
## Existing Project
|
|
213
196
|
|
|
@@ -217,12 +200,18 @@ If you have an existing React project and want to add TanStack Router to it, you
|
|
|
217
200
|
|
|
218
201
|
Before installing TanStack Router, please ensure your project meets the following requirements:
|
|
219
202
|
|
|
220
|
-
|
|
203
|
+
<!-- ::start:framework -->
|
|
204
|
+
|
|
205
|
+
# React
|
|
221
206
|
|
|
222
207
|
- \`react\` v18 or later with \`createRoot\` support.
|
|
223
208
|
- \`react-dom\` v18 or later.
|
|
224
209
|
|
|
225
|
-
|
|
210
|
+
# Solid
|
|
211
|
+
|
|
212
|
+
- \`solid-js\` v1.x.x
|
|
213
|
+
|
|
214
|
+
<!-- ::end:framework -->
|
|
226
215
|
|
|
227
216
|
> [!NOTE]
|
|
228
217
|
> Using TypeScript (\`v5.3.x or higher\`) is recommended for the best development experience, though not strictly required. We aim to support the last 5 minor versions of TypeScript, but using the latest version will help avoid potential issues.
|
|
@@ -233,25 +222,18 @@ TanStack Router is currently only compatible with React (with ReactDOM) and Soli
|
|
|
233
222
|
|
|
234
223
|
To install TanStack Router in your project, run the following command using your preferred package manager:
|
|
235
224
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
# or
|
|
241
|
-
pnpm add @tanstack/react-router
|
|
242
|
-
#or
|
|
243
|
-
yarn add @tanstack/react-router
|
|
244
|
-
# or
|
|
245
|
-
bun add @tanstack/react-router
|
|
246
|
-
# or
|
|
247
|
-
deno add npm:@tanstack/react-router
|
|
248
|
-
\`\`\`
|
|
225
|
+
<!-- ::start:tabs variant="package-managers" -->
|
|
226
|
+
|
|
227
|
+
react: @tanstack/react-router
|
|
228
|
+
solid: @tanstack/solid-router
|
|
249
229
|
|
|
250
|
-
|
|
230
|
+
<!-- ::end:tabs -->
|
|
251
231
|
|
|
252
232
|
Once installed, you can verify the installation by checking your \`package.json\` file for the dependency.
|
|
253
233
|
|
|
254
|
-
|
|
234
|
+
<!-- ::start:framework -->
|
|
235
|
+
|
|
236
|
+
# React
|
|
255
237
|
|
|
256
238
|
\`\`\`json
|
|
257
239
|
{
|
|
@@ -261,7 +243,17 @@ Once installed, you can verify the installation by checking your \`package.json\
|
|
|
261
243
|
}
|
|
262
244
|
\`\`\`
|
|
263
245
|
|
|
264
|
-
|
|
246
|
+
# Solid
|
|
247
|
+
|
|
248
|
+
\`\`\`json
|
|
249
|
+
{
|
|
250
|
+
"dependencies": {
|
|
251
|
+
"@tanstack/solid-router": "^x.x.x"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
\`\`\`
|
|
255
|
+
|
|
256
|
+
<!-- ::end:framework -->
|
|
265
257
|
|
|
266
258
|
# Decisions on Developer Experience
|
|
267
259
|
|
|
@@ -277,9 +269,12 @@ And they are all valid questions. For the most part, people are used to using ro
|
|
|
277
269
|
|
|
278
270
|
But TanStack Router is different. It's not your average routing library. It's not your average state management library. It's not your average anything.
|
|
279
271
|
|
|
272
|
+
> [!TIP]
|
|
273
|
+
> The examples in this guide use React for components and code snippets, but the same principles apply to Solid. The only difference is in the syntax and API of the framework, but the underlying concepts and design decisions are the same.
|
|
274
|
+
|
|
280
275
|
## TanStack Router's origin story
|
|
281
276
|
|
|
282
|
-
It's important to remember that TanStack Router's origins stem from [Nozzle.io](https://nozzle.io)'s need for a client-side routing solution that offered a first-in-class _URL Search Parameters_ experience without compromising on the **_type-safety_** that was required to power its complex dashboards.
|
|
277
|
+
It's important to remember that TanStack Router's origins stem from [Nozzle.io](https://nozzle.io?utm_source=tanstack)'s need for a client-side routing solution that offered a first-in-class _URL Search Parameters_ experience without compromising on the **_type-safety_** that was required to power its complex dashboards.
|
|
283
278
|
|
|
284
279
|
And so, from TanStack Router's very inception, every facet of its design was meticulously thought out to ensure that its type-safety and developer experience were second to none.
|
|
285
280
|
|
|
@@ -511,48 +506,66 @@ When you begin your TanStack Router journey, you'll want these devtools by your
|
|
|
511
506
|
|
|
512
507
|
The devtools are a separate package that you need to install:
|
|
513
508
|
|
|
514
|
-
|
|
515
|
-
npm install @tanstack/react-router-devtools
|
|
516
|
-
\`\`\`
|
|
509
|
+
<!-- ::start:tabs variant="package-manager" -->
|
|
517
510
|
|
|
518
|
-
|
|
511
|
+
react: @tanstack/react-router-devtools
|
|
512
|
+
solid: @tanstack/solid-router-devtools
|
|
519
513
|
|
|
520
|
-
|
|
521
|
-
pnpm add @tanstack/react-router-devtools
|
|
522
|
-
\`\`\`
|
|
514
|
+
<!-- ::end:tabs -->
|
|
523
515
|
|
|
524
|
-
|
|
516
|
+
## Import the Devtools
|
|
525
517
|
|
|
526
|
-
|
|
527
|
-
yarn add @tanstack/react-router-devtools
|
|
528
|
-
\`\`\`
|
|
518
|
+
<!-- ::start:framework -->
|
|
529
519
|
|
|
530
|
-
|
|
520
|
+
# React
|
|
531
521
|
|
|
532
|
-
\`\`\`
|
|
533
|
-
|
|
522
|
+
\`\`\`tsx
|
|
523
|
+
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
|
|
534
524
|
\`\`\`
|
|
535
525
|
|
|
536
|
-
|
|
526
|
+
# Solid
|
|
537
527
|
|
|
538
|
-
\`\`\`
|
|
539
|
-
import { TanStackRouterDevtools } from '@tanstack/
|
|
528
|
+
\`\`\`tsx
|
|
529
|
+
import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'
|
|
540
530
|
\`\`\`
|
|
541
531
|
|
|
532
|
+
<!-- ::end:framework -->
|
|
533
|
+
|
|
542
534
|
## Using Devtools in production
|
|
543
535
|
|
|
544
536
|
The Devtools, if imported as \`TanStackRouterDevtools\` will not be shown in production. If you want to have devtools in an environment with \`process.env.NODE_ENV === 'production'\`, use instead \`TanStackRouterDevtoolsInProd\`, which has all the same options:
|
|
545
537
|
|
|
538
|
+
<!-- ::start:framework -->
|
|
539
|
+
|
|
540
|
+
# React
|
|
541
|
+
|
|
546
542
|
\`\`\`tsx
|
|
547
543
|
import { TanStackRouterDevtoolsInProd } from '@tanstack/react-router-devtools'
|
|
548
544
|
\`\`\`
|
|
549
545
|
|
|
550
|
-
|
|
546
|
+
# Solid
|
|
547
|
+
|
|
548
|
+
\`\`\`tsx
|
|
549
|
+
import { TanStackRouterDevtoolsInProd } from '@tanstack/solid-router-devtools'
|
|
550
|
+
\`\`\`
|
|
551
|
+
|
|
552
|
+
<!-- ::end:framework -->
|
|
553
|
+
|
|
554
|
+
## Using the Devtools in the root route
|
|
551
555
|
|
|
552
556
|
The easiest way for the devtools to work is to render them inside of your root route (or any other route). This will automatically connect the devtools to the router instance.
|
|
553
557
|
|
|
554
|
-
|
|
555
|
-
|
|
558
|
+
<!-- ::start:framework -->
|
|
559
|
+
|
|
560
|
+
# React
|
|
561
|
+
|
|
562
|
+
<!-- ::start:tabs variant="files" -->
|
|
563
|
+
|
|
564
|
+
\`\`\`tsx title="src/routes/__root.tsx"
|
|
565
|
+
import { createRootRoute, Outlet } from '@tanstack/react-router'
|
|
566
|
+
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
|
|
567
|
+
|
|
568
|
+
export const Route = createRootRoute({
|
|
556
569
|
component: () => (
|
|
557
570
|
<>
|
|
558
571
|
<Outlet />
|
|
@@ -560,24 +573,53 @@ const rootRoute = createRootRoute({
|
|
|
560
573
|
</>
|
|
561
574
|
),
|
|
562
575
|
})
|
|
576
|
+
\`\`\`
|
|
563
577
|
|
|
564
|
-
|
|
565
|
-
// ... other routes
|
|
566
|
-
])
|
|
578
|
+
<!-- ::end:tabs -->
|
|
567
579
|
|
|
568
|
-
|
|
569
|
-
routeTree,
|
|
570
|
-
})
|
|
580
|
+
# Solid
|
|
571
581
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
582
|
+
<!-- ::start:tabs variant="files" -->
|
|
583
|
+
|
|
584
|
+
\`\`\`tsx title="src/routes/__root.tsx"
|
|
585
|
+
import { createRootRoute, Outlet } from '@tanstack/solid-router'
|
|
586
|
+
import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'
|
|
587
|
+
|
|
588
|
+
export const Route = createRootRoute({
|
|
589
|
+
component: () => (
|
|
590
|
+
<>
|
|
591
|
+
<Outlet />
|
|
592
|
+
<TanStackRouterDevtools />
|
|
593
|
+
</>
|
|
594
|
+
),
|
|
595
|
+
})
|
|
575
596
|
\`\`\`
|
|
576
597
|
|
|
598
|
+
<!-- ::end:tabs -->
|
|
599
|
+
|
|
600
|
+
<!-- ::end:framework -->
|
|
601
|
+
|
|
577
602
|
## Manually passing the Router Instance
|
|
578
603
|
|
|
579
604
|
If rendering the devtools inside of the \`RouterProvider\` isn't your cup of tea, a \`router\` prop for the devtools accepts the same \`router\` instance you pass to the \`Router\` component. This makes it possible to place the devtools anywhere on the page, not just inside the provider:
|
|
580
605
|
|
|
606
|
+
<!-- ::start:framework -->
|
|
607
|
+
|
|
608
|
+
# React
|
|
609
|
+
|
|
610
|
+
\`\`\`tsx
|
|
611
|
+
function App() {
|
|
612
|
+
return (
|
|
613
|
+
<>
|
|
614
|
+
<RouterProvider router={router} />
|
|
615
|
+
<TanStackRouterDevtools router={router} />
|
|
616
|
+
</>
|
|
617
|
+
)
|
|
618
|
+
}
|
|
619
|
+
\`\`\`
|
|
620
|
+
|
|
621
|
+
# Solid
|
|
622
|
+
|
|
581
623
|
\`\`\`tsx
|
|
582
624
|
function App() {
|
|
583
625
|
return (
|
|
@@ -589,25 +631,44 @@ function App() {
|
|
|
589
631
|
}
|
|
590
632
|
\`\`\`
|
|
591
633
|
|
|
634
|
+
<!-- ::end:framework -->
|
|
635
|
+
|
|
592
636
|
## Floating Mode
|
|
593
637
|
|
|
594
638
|
Floating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.
|
|
595
639
|
|
|
596
|
-
Place the following code as high in your
|
|
640
|
+
Place the following code as high in your app as you can. The closer it is to the root of the page, the better it will work!
|
|
597
641
|
|
|
598
|
-
|
|
599
|
-
|
|
642
|
+
<!-- ::start:framework -->
|
|
643
|
+
|
|
644
|
+
# React
|
|
645
|
+
|
|
646
|
+
\`\`\`tsx
|
|
647
|
+
function App() {
|
|
648
|
+
return (
|
|
649
|
+
<>
|
|
650
|
+
<RouterProvider router={router} />
|
|
651
|
+
<TanStackRouterDevtools initialIsOpen={false} />
|
|
652
|
+
</>
|
|
653
|
+
)
|
|
654
|
+
}
|
|
655
|
+
\`\`\`
|
|
656
|
+
|
|
657
|
+
# Solid
|
|
600
658
|
|
|
659
|
+
\`\`\`tsx
|
|
601
660
|
function App() {
|
|
602
661
|
return (
|
|
603
662
|
<>
|
|
604
|
-
<
|
|
663
|
+
<RouterProvider router={router} />
|
|
605
664
|
<TanStackRouterDevtools initialIsOpen={false} />
|
|
606
665
|
</>
|
|
607
666
|
)
|
|
608
667
|
}
|
|
609
668
|
\`\`\`
|
|
610
669
|
|
|
670
|
+
<!-- ::end:framework -->
|
|
671
|
+
|
|
611
672
|
### Devtools Options
|
|
612
673
|
|
|
613
674
|
- \`router: Router\`
|
|
@@ -635,32 +696,63 @@ function App() {
|
|
|
635
696
|
|
|
636
697
|
To control the position of the devtools, import the \`TanStackRouterDevtoolsPanel\`:
|
|
637
698
|
|
|
638
|
-
|
|
699
|
+
<!-- ::start:framework -->
|
|
700
|
+
|
|
701
|
+
# React
|
|
702
|
+
|
|
703
|
+
\`\`\`tsx
|
|
639
704
|
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
|
|
640
705
|
\`\`\`
|
|
641
706
|
|
|
707
|
+
# Solid
|
|
708
|
+
|
|
709
|
+
\`\`\`tsx
|
|
710
|
+
import { TanStackRouterDevtoolsPanel } from '@tanstack/solid-router-devtools'
|
|
711
|
+
\`\`\`
|
|
712
|
+
|
|
713
|
+
<!-- ::end:framework -->
|
|
714
|
+
|
|
642
715
|
It can then be attached to provided shadow DOM target:
|
|
643
716
|
|
|
644
|
-
|
|
717
|
+
<!-- ::start:framework -->
|
|
718
|
+
|
|
719
|
+
# React
|
|
720
|
+
|
|
721
|
+
\`\`\`tsx
|
|
645
722
|
<TanStackRouterDevtoolsPanel
|
|
646
723
|
shadowDOMTarget={shadowContainer}
|
|
647
724
|
router={router}
|
|
648
725
|
/>
|
|
649
726
|
\`\`\`
|
|
650
727
|
|
|
728
|
+
# Solid
|
|
729
|
+
|
|
730
|
+
\`\`\`tsx
|
|
731
|
+
<TanStackRouterDevtoolsPanel
|
|
732
|
+
shadowDOMTarget={shadowContainer}
|
|
733
|
+
router={router}
|
|
734
|
+
/>
|
|
735
|
+
\`\`\`
|
|
736
|
+
|
|
737
|
+
<!-- ::end:framework -->
|
|
738
|
+
|
|
651
739
|
Click [here](https://tanstack.com/router/latest/docs/framework/react/examples/basic-devtools-panel) to see a live example of this in StackBlitz.
|
|
652
740
|
|
|
653
741
|
## Embedded Mode
|
|
654
742
|
|
|
655
743
|
Embedded Mode will embed the devtools as a regular component in your application. You can style it however you'd like after that!
|
|
656
744
|
|
|
657
|
-
|
|
745
|
+
<!-- ::start:framework -->
|
|
746
|
+
|
|
747
|
+
# React
|
|
748
|
+
|
|
749
|
+
\`\`\`tsx
|
|
658
750
|
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
|
|
659
751
|
|
|
660
752
|
function App() {
|
|
661
753
|
return (
|
|
662
754
|
<>
|
|
663
|
-
<
|
|
755
|
+
<RouterProvider router={router} />
|
|
664
756
|
<TanStackRouterDevtoolsPanel
|
|
665
757
|
router={router}
|
|
666
758
|
style={styles}
|
|
@@ -671,14 +763,50 @@ function App() {
|
|
|
671
763
|
}
|
|
672
764
|
\`\`\`
|
|
673
765
|
|
|
766
|
+
# Solid
|
|
767
|
+
|
|
768
|
+
\`\`\`tsx
|
|
769
|
+
import { TanStackRouterDevtoolsPanel } from '@tanstack/solid-router-devtools'
|
|
770
|
+
|
|
771
|
+
function App() {
|
|
772
|
+
return (
|
|
773
|
+
<>
|
|
774
|
+
<RouterProvider router={router} />
|
|
775
|
+
<TanStackRouterDevtoolsPanel
|
|
776
|
+
router={router}
|
|
777
|
+
style={styles}
|
|
778
|
+
class={className}
|
|
779
|
+
/>
|
|
780
|
+
</>
|
|
781
|
+
)
|
|
782
|
+
}
|
|
783
|
+
\`\`\`
|
|
784
|
+
|
|
785
|
+
<!-- ::end:framework -->
|
|
786
|
+
|
|
674
787
|
### DevtoolsPanel Options
|
|
675
788
|
|
|
676
789
|
- \`router: Router\`
|
|
677
790
|
- The router instance to connect to.
|
|
678
|
-
|
|
791
|
+
|
|
792
|
+
<!-- ::start:framework -->
|
|
793
|
+
|
|
794
|
+
# React
|
|
795
|
+
|
|
796
|
+
- \`style?: StyleObject\`
|
|
679
797
|
- The standard React style object used to style a component with inline styles.
|
|
680
|
-
- \`className
|
|
798
|
+
- \`className?: string\`
|
|
681
799
|
- The standard React className property used to style a component with classes.
|
|
800
|
+
|
|
801
|
+
# Solid
|
|
802
|
+
|
|
803
|
+
- \`style?: StyleObject\`
|
|
804
|
+
- The standard Solid style object used to style a component with inline styles.
|
|
805
|
+
- \`class?: string\`
|
|
806
|
+
- The standard Solid class property used to style a component with classes.
|
|
807
|
+
|
|
808
|
+
<!-- ::end:framework -->
|
|
809
|
+
|
|
682
810
|
- \`isOpen?: boolean\`
|
|
683
811
|
- A boolean variable indicating whether the panel is open or closed.
|
|
684
812
|
- \`setIsOpen?: (isOpen: boolean) => void\`
|
|
@@ -716,7 +844,6 @@ You should commit this file into git so that other developers can use it to buil
|
|
|
716
844
|
## Can I conditionally render the Root Route component?
|
|
717
845
|
|
|
718
846
|
No, the root route is always rendered as it is the entry point of your application.
|
|
719
|
-
|
|
720
847
|
If you need to conditionally render a route's component, this usually means that the page content needs to be different based on some condition (e.g. user authentication). For this use case, you should use a [Layout Route](./routing/routing-concepts.md#layout-routes) or a [Pathless Layout Route](./routing/routing-concepts.md#pathless-layout-routes) to conditionally render the content.
|
|
721
848
|
|
|
722
849
|
You can restrict access to these routes using a conditional check in the \`beforeLoad\` function of the route.
|
|
@@ -724,6 +851,10 @@ You can restrict access to these routes using a conditional check in the \`befor
|
|
|
724
851
|
<details>
|
|
725
852
|
<summary>What does this look like?</summary>
|
|
726
853
|
|
|
854
|
+
<!-- ::start:framework -->
|
|
855
|
+
|
|
856
|
+
# React
|
|
857
|
+
|
|
727
858
|
\`\`\`tsx
|
|
728
859
|
// src/routes/_pathless-layout.tsx
|
|
729
860
|
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
|
@@ -752,6 +883,38 @@ function PathlessLayoutRouteComponent() {
|
|
|
752
883
|
}
|
|
753
884
|
\`\`\`
|
|
754
885
|
|
|
886
|
+
# Solid
|
|
887
|
+
|
|
888
|
+
\`\`\`tsx
|
|
889
|
+
// src/routes/_pathless-layout.tsx
|
|
890
|
+
import { createFileRoute, Outlet } from '@tanstack/solid-router'
|
|
891
|
+
import { isAuthenticated } from '../utils/auth'
|
|
892
|
+
|
|
893
|
+
export const Route = createFileRoute('/_pathless-layout', {
|
|
894
|
+
beforeLoad: async () => {
|
|
895
|
+
// Check if the user is authenticated
|
|
896
|
+
const authed = await isAuthenticated()
|
|
897
|
+
if (!authed) {
|
|
898
|
+
// Redirect the user to the login page
|
|
899
|
+
return '/login'
|
|
900
|
+
}
|
|
901
|
+
},
|
|
902
|
+
component: PathlessLayoutRouteComponent,
|
|
903
|
+
// ...
|
|
904
|
+
})
|
|
905
|
+
|
|
906
|
+
function PathlessLayoutRouteComponent() {
|
|
907
|
+
return (
|
|
908
|
+
<div>
|
|
909
|
+
<h1>You are authed</h1>
|
|
910
|
+
<Outlet />
|
|
911
|
+
</div>
|
|
912
|
+
)
|
|
913
|
+
}
|
|
914
|
+
\`\`\`
|
|
915
|
+
|
|
916
|
+
<!-- ::end:framework -->
|
|
917
|
+
|
|
755
918
|
</details>
|
|
756
919
|
|
|
757
920
|
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.161.1",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"tiny-invariant": "^1.3.3",
|
|
83
83
|
"tiny-warning": "^1.0.3",
|
|
84
84
|
"@tanstack/history": "1.154.14",
|
|
85
|
-
"@tanstack/router-core": "1.
|
|
85
|
+
"@tanstack/router-core": "1.161.1"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@testing-library/jest-dom": "^6.6.3",
|
package/src/Asset.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { isServer } from '@tanstack/router-core/isServer'
|
|
3
3
|
import { useRouter } from './useRouter'
|
|
4
|
+
import { useHydrated } from './ClientOnly'
|
|
4
5
|
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
5
6
|
|
|
6
7
|
interface ScriptAttrs {
|
|
@@ -49,12 +50,24 @@ function Script({
|
|
|
49
50
|
children?: string
|
|
50
51
|
}) {
|
|
51
52
|
const router = useRouter()
|
|
53
|
+
const hydrated = useHydrated()
|
|
52
54
|
const dataScript =
|
|
53
55
|
typeof attrs?.type === 'string' &&
|
|
54
56
|
attrs.type !== '' &&
|
|
55
57
|
attrs.type !== 'text/javascript' &&
|
|
56
58
|
attrs.type !== 'module'
|
|
57
59
|
|
|
60
|
+
if (
|
|
61
|
+
process.env.NODE_ENV !== 'production' &&
|
|
62
|
+
attrs?.src &&
|
|
63
|
+
typeof children === 'string' &&
|
|
64
|
+
children.trim().length
|
|
65
|
+
) {
|
|
66
|
+
console.warn(
|
|
67
|
+
'[TanStack Router] <Script> received both `src` and `children`. The `children` content will be ignored. Remove `children` or remove `src`.',
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
58
71
|
React.useEffect(() => {
|
|
59
72
|
if (dataScript) return
|
|
60
73
|
|
|
@@ -151,41 +164,56 @@ function Script({
|
|
|
151
164
|
return undefined
|
|
152
165
|
}, [attrs, children, dataScript])
|
|
153
166
|
|
|
154
|
-
|
|
155
|
-
|
|
167
|
+
// --- Server rendering ---
|
|
168
|
+
if (isServer ?? router.isServer) {
|
|
169
|
+
if (attrs?.src) {
|
|
170
|
+
return <script {...attrs} suppressHydrationWarning />
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (typeof children === 'string') {
|
|
156
174
|
return (
|
|
157
175
|
<script
|
|
158
176
|
{...attrs}
|
|
159
|
-
suppressHydrationWarning
|
|
160
177
|
dangerouslySetInnerHTML={{ __html: children }}
|
|
178
|
+
suppressHydrationWarning
|
|
161
179
|
/>
|
|
162
180
|
)
|
|
163
181
|
}
|
|
164
182
|
|
|
165
|
-
|
|
166
|
-
// render an empty script on the client just to avoid hydration errors
|
|
167
|
-
return (
|
|
168
|
-
<script
|
|
169
|
-
suppressHydrationWarning
|
|
170
|
-
dangerouslySetInnerHTML={{ __html: '' }}
|
|
171
|
-
{...rest}
|
|
172
|
-
></script>
|
|
173
|
-
)
|
|
183
|
+
return null
|
|
174
184
|
}
|
|
175
185
|
|
|
176
|
-
|
|
177
|
-
return <script {...attrs} suppressHydrationWarning />
|
|
178
|
-
}
|
|
186
|
+
// --- Client rendering ---
|
|
179
187
|
|
|
180
|
-
|
|
188
|
+
// Data scripts (e.g. application/ld+json) are rendered in the tree;
|
|
189
|
+
// the useEffect intentionally skips them.
|
|
190
|
+
if (dataScript && typeof children === 'string') {
|
|
181
191
|
return (
|
|
182
192
|
<script
|
|
183
193
|
{...attrs}
|
|
184
|
-
dangerouslySetInnerHTML={{ __html: children }}
|
|
185
194
|
suppressHydrationWarning
|
|
195
|
+
dangerouslySetInnerHTML={{ __html: children }}
|
|
186
196
|
/>
|
|
187
197
|
)
|
|
188
198
|
}
|
|
189
199
|
|
|
200
|
+
// During hydration (before useEffect has fired), render the script element
|
|
201
|
+
// to match the server-rendered HTML and avoid structural hydration mismatches.
|
|
202
|
+
// After hydration, return null — the useEffect handles imperative injection.
|
|
203
|
+
if (!hydrated) {
|
|
204
|
+
if (attrs?.src) {
|
|
205
|
+
return <script {...attrs} suppressHydrationWarning />
|
|
206
|
+
}
|
|
207
|
+
if (typeof children === 'string') {
|
|
208
|
+
return (
|
|
209
|
+
<script
|
|
210
|
+
{...attrs}
|
|
211
|
+
dangerouslySetInnerHTML={{ __html: children }}
|
|
212
|
+
suppressHydrationWarning
|
|
213
|
+
/>
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
190
218
|
return null
|
|
191
219
|
}
|