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
* Add Segment Validators to allow more complex path matching.
This allows to add validator functions at the segment level.
* Remove the ~ prefix, : colon is already enough.
* Apply matchFilter naming and extend matching functionality
* Adding type inference for Route array paths
* Update test on route specs.
Co-authored-by: Jorren <jorrenhendriks@gmail.com>
Copy file name to clipboardExpand all lines: README.md
+89-53Lines changed: 89 additions & 53 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@
6
6
7
7
A router lets you change your view based on the URL in the browser. This allows your "single-page" application to simulate a traditional multipage site. To use Solid Router, you specify components called Routes that depend on the value of the URL (the "path"), and the router handles the mechanism of swapping them in and out.
8
8
9
-
Solid Router is a universal router for SolidJS - it works whether you're rendering on the client or on the server. It was inspired by and combines paradigms of React Router and the Ember Router. Routes can be defined directly in your app's template using JSX, but you can also pass your route configuration directly as an object. It also supports nested routing, so navigation can change a part of a component, rather than completely replacing it.
9
+
Solid Router is a universal router for SolidJS - it works whether you're rendering on the client or on the server. It was inspired by and combines paradigms of React Router and the Ember Router. Routes can be defined directly in your app's template using JSX, but you can also pass your route configuration directly as an object. It also supports nested routing, so navigation can change a part of a component, rather than completely replacing it.
10
10
11
11
It supports all of Solid's SSR methods and has Solid's transitions baked in, so use it freely with suspense, resources, and lazy components. Solid Router also allows you to define a data function that loads parallel to the routes ([render-as-you-fetch](https://epicreact.dev/render-as-you-fetch/)).
12
12
@@ -16,8 +16,8 @@ It supports all of Solid's SSR methods and has Solid's transitions baked in, so
16
16
-[Create Links to Your Routes](#create-links-to-your-routes)
17
17
-[Dynamic Routes](#dynamic-routes)
18
18
-[Data Functions](#data-functions)
19
-
-[Nested Routes](#nested-routes)
20
-
-[Hash Mode Router](#hash-mode-router)
19
+
-[Nested Routes](#nested-routes)
20
+
-[Hash Mode Router](#hash-mode-router)
21
21
-[Config Based Routing](#config-based-routing)
22
22
-[Router Primitives](#router-primitives)
23
23
-[useParams](#useparams)
@@ -63,17 +63,16 @@ Solid Router allows you to configure your routes using JSX:
63
63
64
64
1. Use the `Routes` component to specify where the routes should appear in your app.
65
65
66
-
67
66
```jsx
68
67
import { Routes, Route } from"@solidjs/router"
69
68
70
69
exportdefaultfunctionApp() {
71
70
return<>
72
-
<h1>My Site with Lots of Pages</h1>
71
+
<h1>My Site with Lots of Pages</h1>
73
72
<Routes>
74
73
75
74
</Routes>
76
-
</>
75
+
</>
77
76
}
78
77
```
79
78
@@ -87,13 +86,13 @@ import Users from "./pages/Users"
87
86
88
87
exportdefaultfunctionApp() {
89
88
return<>
90
-
<h1>My Site with Lots of Pages</h1>
91
-
<Routes>
92
-
<Route path="/users" component={Users} />
93
-
<Route path="/" component={Home} />
94
-
<Route path="/about" element={<div>This site was made with Solid</div>} />
95
-
</Routes>
96
-
</>
89
+
<h1>My Site with Lots of Pages</h1>
90
+
<Routes>
91
+
<Route path="/users" component={Users} />
92
+
<Route path="/" component={Home} />
93
+
<Route path="/about" element={<div>This site was made with Solid</div>} />
94
+
</Routes>
95
+
</>
97
96
}
98
97
```
99
98
@@ -109,13 +108,13 @@ const Home = lazy(() => import("./pages/Home"));
109
108
110
109
exportdefaultfunctionApp() {
111
110
return<>
112
-
<h1>My Site with Lots of Pages</h1>
113
-
<Routes>
114
-
<Route path="/users" component={Users} />
115
-
<Route path="/" component={Home} />
116
-
<Route path="/about" element={<div>This site was made with Solid</div>} />
117
-
</Routes>
118
-
</>
111
+
<h1>My Site with Lots of Pages</h1>
112
+
<Routes>
113
+
<Route path="/users" component={Users} />
114
+
<Route path="/" component={Home} />
115
+
<Route path="/about" element={<div>This site was made with Solid</div>} />
116
+
</Routes>
117
+
</>
119
118
}
120
119
```
121
120
@@ -131,17 +130,17 @@ const Home = lazy(() => import("./pages/Home"));
131
130
132
131
exportdefaultfunctionApp() {
133
132
return<>
134
-
<h1>My Site with Lots of Pages</h1>
135
-
<nav>
136
-
<A href="/about">About</A>
137
-
<A href="/">Home</A>
138
-
</nav>
139
-
<Routes>
140
-
<Route path="/users" component={Users} />
141
-
<Route path="/" component={Home} />
142
-
<Route path="/about" element={<div>This site was made with Solid</div>} />
143
-
</Routes>
144
-
</>
133
+
<h1>My Site with Lots of Pages</h1>
134
+
<nav>
135
+
<A href="/about">About</A>
136
+
<A href="/">Home</A>
137
+
</nav>
138
+
<Routes>
139
+
<Route path="/users" component={Users} />
140
+
<Route path="/" component={Home} />
141
+
<Route path="/about" element={<div>This site was made with Solid</div>} />
142
+
</Routes>
143
+
</>
145
144
}
146
145
```
147
146
@@ -163,7 +162,7 @@ Solid Router provides a `Navigate` component that works similarly to `A`, but it
163
162
164
163
```jsx
165
164
functiongetPath ({navigate, location}) {
166
-
//navigate is the result of calling useNavigate(); location is the result of calling useLocation().
165
+
//navigate is the result of calling useNavigate(); location is the result of calling useLocation().
167
166
//You can use those to dynamically determine a path to navigate to
168
167
return"/some-path";
169
168
}
@@ -174,7 +173,7 @@ function getPath ({navigate, location}) {
174
173
175
174
## Dynamic Routes
176
175
177
-
If you don't know the path ahead of time, you might want to treat part of the path as a flexible parameter that is passed on to the component.
176
+
If you don't know the path ahead of time, you might want to treat part of the path as a flexible parameter that is passed on to the component.
178
177
179
178
```jsx
180
179
import { lazy } from"solid-js";
@@ -185,21 +184,63 @@ const Home = lazy(() => import("./pages/Home"));
185
184
186
185
exportdefaultfunctionApp() {
187
186
return<>
188
-
<h1>My Site with Lots of Pages</h1>
189
-
<Routes>
190
-
<Route path="/users" component={Users} />
191
-
<Route path="/users/:id" component={User} />
192
-
<Route path="/" component={Home} />
193
-
<Route path="/about" element={<div>This site was made with Solid</div>} />
194
-
</Routes>
195
-
</>
187
+
<h1>My Site with Lots of Pages</h1>
188
+
<Routes>
189
+
<Route path="/users" component={Users} />
190
+
<Route path="/users/:id" component={User} />
191
+
<Route path="/" component={Home} />
192
+
<Route path="/about" element={<div>This site was made with Solid</div>} />
193
+
</Routes>
194
+
</>
196
195
}
197
196
```
198
197
199
198
The colon indicates that `id` can be any string, and as long as the URL fits that pattern, the `User` component will show.
200
199
201
200
You can then access that `id` from within a route component with `useParams`:
202
201
202
+
---
203
+
204
+
Each path parameter can be validated using a `MatchFilter`.
205
+
This allows for more complex routing descriptions than just checking the presence of a parameter.
206
+
207
+
```tsx
208
+
import {lazy} from"solid-js";
209
+
import {Routes, Route} from"@solidjs/router"
210
+
importtype {SegmentValidators} from"./types";
211
+
212
+
const Users =lazy(() =>import("./pages/Users"));
213
+
const User =lazy(() =>import("./pages/User"));
214
+
const Home =lazy(() =>import("./pages/Home"));
215
+
216
+
const filters:MatchFilters= {
217
+
parent: ['mom', 'dad'], // allow enum values
218
+
id:/^\d+$/, // only allow numbers
219
+
withHtmlExtension: (v:string) =>v.length>5&&v.endsWith('.html') // we want an `*.html` extension
Here, we have added the `matchFilters` prop. This allows us to validate the `parent`, `id` and `withHtmlExtension` parameters against the filters defined in `filters`.
233
+
If the validation fails, the route will not match.
234
+
235
+
So in this example:
236
+
237
+
-`/users/mom/123/contact.html` would match,
238
+
-`/users/dad/123/about.html` would match,
239
+
-`/users/aunt/123/contact.html` would not match as `:parent` is not 'mom' or 'dad',
240
+
-`/users/mom/me/contact.html` would not match as `:id` is not a number,
241
+
-`/users/dad/123/contact` would not match as `:withHtmlExtension` is missing `.html`.
242
+
243
+
---
203
244
204
245
```jsx
205
246
//async fetching function
@@ -250,12 +291,10 @@ Routes also support defining multiple paths using an array. This allows a route
In the [above example](#dynamic-routes), the User component is lazy-loaded and then the data is fetched. With route data functions, we can instead start fetching the data parallel to loading the route, so we can use the data as soon as possible.
256
296
257
-
To do this, create a function that fetches and returns the data using `createResource`. Then pass that function to the `data` prop of the `Route` component.
258
-
297
+
To do this, create a function that fetches and returns the data using `createResource`. Then pass that function to the `data` prop of the `Route` component.
259
298
260
299
```js
261
300
import { lazy } from"solid-js";
@@ -299,7 +338,7 @@ A common pattern is to export the data function that corresponds to a route in a
@@ -341,15 +380,14 @@ Only leaf Route nodes (innermost `Route` components) are given a route. If you w
341
380
342
381
You can also take advantage of nesting by adding a parent element with an `<Outlet/>`.
343
382
```jsx
344
-
345
383
import { Outlet } from"@solidjs/router";
346
384
347
385
functionPageWrapper () {
348
386
return<div>
349
-
<h1> We love our users!</h1>
387
+
<h1> We love our users!</h1>
350
388
<Outlet/>
351
-
<A href="/">Back Home</A>
352
-
</div>
389
+
<A href="/">Back Home</A>
390
+
</div>
353
391
}
354
392
355
393
<Route path="/users" component={PageWrapper}>
@@ -369,7 +407,7 @@ You can nest indefinitely - just remember that only leaf nodes will become their
369
407
</Route>
370
408
```
371
409
372
-
If you declare a `data` function on a parent and a child, the result of the parent's data function will be passed to the child's data function as the `data` property of the argument, as described in the last section. This works even if it isn't a direct child, because by default every route forwards its parent's data.
410
+
If you declare a `data` function on a parent and a child, the result of the parent's data function will be passed to the child's data function as the `data` property of the argument, as described in the last section. This works even if it isn't a direct child, because by default every route forwards its parent's data.
0 commit comments