2
2
3
3
import type { Component , JSX , Owner } from "solid-js" ;
4
4
import { type RequestEvent , getRequestEvent , isServer } from "solid-js/web" ;
5
- import { children , createMemo , createRoot , getOwner , mergeProps , on , Show } from "solid-js" ;
5
+ import {
6
+ children ,
7
+ createMemo ,
8
+ createRoot ,
9
+ getOwner ,
10
+ mergeProps ,
11
+ on ,
12
+ Show ,
13
+ untrack
14
+ } from "solid-js" ;
6
15
import {
7
16
createBranches ,
8
17
createRouteContext ,
@@ -20,9 +29,10 @@ import type {
20
29
RouterIntegration ,
21
30
RouterContext ,
22
31
Branch ,
23
- RouteSectionProps
32
+ RouteSectionProps ,
33
+ Location
24
34
} from "../types.js" ;
25
- import { createMemoObject , extractSearchParams } from "../utils.js" ;
35
+ import { createMemoObject } from "../utils.js" ;
26
36
27
37
export type BaseRouterProps = {
28
38
base ?: string ;
@@ -41,24 +51,46 @@ export const createRouterComponent = (router: RouterIntegration) => (props: Base
41
51
| RouteDefinition
42
52
| RouteDefinition [ ] ;
43
53
44
- const branches = createMemo ( ( ) =>
45
- createBranches (
46
- props . root ? { component : props . root , load : props . rootLoad , children : routeDefs ( ) } : routeDefs ( ) ,
47
- props . base || ""
48
- )
49
- ) ;
54
+ const branches = createMemo ( ( ) => createBranches ( routeDefs ( ) , props . base || "" ) ) ;
50
55
let context : Owner ;
51
- const routerState = createRouterContext ( router , ( ) => context , branches , { base, singleFlight : props . singleFlight } ) ;
56
+ const routerState = createRouterContext ( router , ( ) => context , branches , {
57
+ base,
58
+ singleFlight : props . singleFlight
59
+ } ) ;
60
+ const location = routerState . location ;
52
61
router . create && router . create ( routerState ) ;
53
62
54
63
return (
55
64
< RouterContextObj . Provider value = { routerState } >
56
- { ( context = getOwner ( ) ! ) && null }
57
- < Routes routerState = { routerState } branches = { branches ( ) } />
65
+ < Root location = { location } root = { props . root } load = { props . rootLoad } >
66
+ { ( context = getOwner ( ) ! ) && null }
67
+ < Routes routerState = { routerState } branches = { branches ( ) } />
68
+ </ Root >
58
69
</ RouterContextObj . Provider >
59
70
) ;
60
71
} ;
61
72
73
+ function Root ( props : {
74
+ location : Location < unknown > ;
75
+ root ?: Component < RouteSectionProps > ;
76
+ load ?: RouteLoadFunc ;
77
+ children : JSX . Element ;
78
+ } ) {
79
+ const location = props . location ;
80
+ const data = createMemo (
81
+ ( ) => props . load && untrack ( ( ) => props . load ! ( { params : { } , location, intent : "preload" } ) )
82
+ ) ;
83
+ return (
84
+ < Show when = { props . root } keyed fallback = { props . children } >
85
+ { Root => (
86
+ < Root params = { { } } location = { location } data = { data ( ) } >
87
+ { props . children }
88
+ </ Root >
89
+ ) }
90
+ </ Show >
91
+ ) ;
92
+ }
93
+
62
94
function Routes ( props : { routerState : RouterContext ; branches : Branch [ ] } ) {
63
95
const matches = createMemo ( ( ) =>
64
96
getRouteMatches ( props . branches , props . routerState . location . pathname )
@@ -67,7 +99,7 @@ function Routes(props: { routerState: RouterContext; branches: Branch[] }) {
67
99
if ( isServer ) {
68
100
const e = getRequestEvent ( ) ;
69
101
if ( e && e . router && e . router . dataOnly ) {
70
- dataOnly ( e , props . branches ) ;
102
+ dataOnly ( e , props . routerState , props . branches ) ;
71
103
return ;
72
104
}
73
105
e &&
@@ -129,11 +161,7 @@ function Routes(props: { routerState: RouterContext; branches: Branch[] }) {
129
161
return next ;
130
162
} )
131
163
) ;
132
- return (
133
- < Show when = { routeStates ( ) && root } keyed >
134
- { route => < RouteContextObj . Provider value = { route } > { route . outlet ( ) } </ RouteContextObj . Provider > }
135
- </ Show >
136
- ) ;
164
+ return createOutlet ( ( ) => routeStates ( ) && root ) ( ) ;
137
165
}
138
166
139
167
const createOutlet = ( child : ( ) => RouteContext | undefined ) => {
@@ -163,27 +191,21 @@ export const Route = <S extends string, T = unknown>(props: RouteProps<S, T>) =>
163
191
} ;
164
192
165
193
// for data only mode with single flight mutations
166
- function dataOnly ( event : RequestEvent , branches : Branch [ ] ) {
194
+ function dataOnly ( event : RequestEvent , routerState : RouterContext , branches : Branch [ ] ) {
167
195
const url = new URL ( event . request . url ) ;
168
196
const prevMatches = getRouteMatches (
169
197
branches ,
170
198
new URL ( event . router ! . previousUrl || event . request . url ) . pathname
171
199
) ;
172
200
const matches = getRouteMatches ( branches , url . pathname ) ;
173
201
for ( let match = 0 ; match < matches . length ; match ++ ) {
174
- if ( ! prevMatches [ match ] || matches [ match ] . route !== prevMatches [ match ] . route ) event . router ! . dataOnly = true ;
202
+ if ( ! prevMatches [ match ] || matches [ match ] . route !== prevMatches [ match ] . route )
203
+ event . router ! . dataOnly = true ;
175
204
const { route, params } = matches [ match ] ;
176
205
route . load &&
177
206
route . load ( {
178
207
params,
179
- location : {
180
- pathname : url . pathname ,
181
- search : url . search ,
182
- hash : url . hash ,
183
- query : extractSearchParams ( url ) ,
184
- state : null ,
185
- key : ""
186
- } ,
208
+ location : routerState . location ,
187
209
intent : "preload"
188
210
} ) ;
189
211
}
0 commit comments