@solidjs/router 0.8.1 → 0.8.3
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/README.md +186 -87
- package/dist/components.d.ts +7 -7
- package/dist/components.jsx +2 -2
- package/dist/index.js +3 -2
- package/dist/routing.js +2 -2
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ It supports all of Solid's SSR methods and has Solid's transitions baked in, so
|
|
|
30
30
|
- [useMatch](#usematch)
|
|
31
31
|
- [useRoutes](#useroutes)
|
|
32
32
|
- [useBeforeLeave](#usebeforeleave)
|
|
33
|
+
- [SPAs in Deployed Environments](#spas-in-deployed-environments)
|
|
33
34
|
|
|
34
35
|
## Getting Started
|
|
35
36
|
|
|
@@ -65,35 +66,40 @@ Solid Router allows you to configure your routes using JSX:
|
|
|
65
66
|
1. Use the `Routes` component to specify where the routes should appear in your app.
|
|
66
67
|
|
|
67
68
|
```jsx
|
|
68
|
-
import { Routes, Route } from "@solidjs/router"
|
|
69
|
+
import { Routes, Route } from "@solidjs/router";
|
|
69
70
|
|
|
70
71
|
export default function App() {
|
|
71
|
-
return
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
72
74
|
<h1>My Site with Lots of Pages</h1>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
</Routes>
|
|
75
|
+
<Routes></Routes>
|
|
76
76
|
</>
|
|
77
|
+
);
|
|
77
78
|
}
|
|
78
79
|
```
|
|
79
80
|
|
|
80
81
|
2. Add each route using the `Route` component, specifying a path and an element or component to render when the user navigates to that path.
|
|
81
82
|
|
|
82
83
|
```jsx
|
|
83
|
-
import { Routes, Route } from "@solidjs/router"
|
|
84
|
+
import { Routes, Route } from "@solidjs/router";
|
|
84
85
|
|
|
85
|
-
import Home from "./pages/Home"
|
|
86
|
-
import Users from "./pages/Users"
|
|
86
|
+
import Home from "./pages/Home";
|
|
87
|
+
import Users from "./pages/Users";
|
|
87
88
|
|
|
88
89
|
export default function App() {
|
|
89
|
-
return
|
|
90
|
+
return (
|
|
91
|
+
<>
|
|
90
92
|
<h1>My Site with Lots of Pages</h1>
|
|
91
93
|
<Routes>
|
|
92
94
|
<Route path="/users" component={Users} />
|
|
93
95
|
<Route path="/" component={Home} />
|
|
94
|
-
<Route
|
|
96
|
+
<Route
|
|
97
|
+
path="/about"
|
|
98
|
+
element={<div>This site was made with Solid</div>}
|
|
99
|
+
/>
|
|
95
100
|
</Routes>
|
|
96
101
|
</>
|
|
102
|
+
);
|
|
97
103
|
}
|
|
98
104
|
```
|
|
99
105
|
|
|
@@ -103,19 +109,24 @@ This way, the `Users` and `Home` components will only be loaded if you're naviga
|
|
|
103
109
|
|
|
104
110
|
```jsx
|
|
105
111
|
import { lazy } from "solid-js";
|
|
106
|
-
import { Routes, Route } from "@solidjs/router"
|
|
112
|
+
import { Routes, Route } from "@solidjs/router";
|
|
107
113
|
const Users = lazy(() => import("./pages/Users"));
|
|
108
114
|
const Home = lazy(() => import("./pages/Home"));
|
|
109
115
|
|
|
110
116
|
export default function App() {
|
|
111
|
-
return
|
|
117
|
+
return (
|
|
118
|
+
<>
|
|
112
119
|
<h1>My Site with Lots of Pages</h1>
|
|
113
120
|
<Routes>
|
|
114
121
|
<Route path="/users" component={Users} />
|
|
115
122
|
<Route path="/" component={Home} />
|
|
116
|
-
<Route
|
|
123
|
+
<Route
|
|
124
|
+
path="/about"
|
|
125
|
+
element={<div>This site was made with Solid</div>}
|
|
126
|
+
/>
|
|
117
127
|
</Routes>
|
|
118
128
|
</>
|
|
129
|
+
);
|
|
119
130
|
}
|
|
120
131
|
```
|
|
121
132
|
|
|
@@ -125,12 +136,13 @@ Use the `A` component to create an anchor tag that takes you to a route:
|
|
|
125
136
|
|
|
126
137
|
```jsx
|
|
127
138
|
import { lazy } from "solid-js";
|
|
128
|
-
import { Routes, Route, A } from "@solidjs/router"
|
|
139
|
+
import { Routes, Route, A } from "@solidjs/router";
|
|
129
140
|
const Users = lazy(() => import("./pages/Users"));
|
|
130
141
|
const Home = lazy(() => import("./pages/Home"));
|
|
131
142
|
|
|
132
143
|
export default function App() {
|
|
133
|
-
return
|
|
144
|
+
return (
|
|
145
|
+
<>
|
|
134
146
|
<h1>My Site with Lots of Pages</h1>
|
|
135
147
|
<nav>
|
|
136
148
|
<A href="/about">About</A>
|
|
@@ -139,37 +151,41 @@ export default function App() {
|
|
|
139
151
|
<Routes>
|
|
140
152
|
<Route path="/users" component={Users} />
|
|
141
153
|
<Route path="/" component={Home} />
|
|
142
|
-
<Route
|
|
154
|
+
<Route
|
|
155
|
+
path="/about"
|
|
156
|
+
element={<div>This site was made with Solid</div>}
|
|
157
|
+
/>
|
|
143
158
|
</Routes>
|
|
144
159
|
</>
|
|
160
|
+
);
|
|
145
161
|
}
|
|
146
162
|
```
|
|
147
163
|
|
|
148
164
|
The `<A>` tag also has an `active` class if its href matches the current location, and `inactive` otherwise. **Note:** By default matching includes locations that are descendents (eg. href `/users` matches locations `/users` and `/users/123`), use the boolean `end` prop to prevent matching these. This is particularly useful for links to the root route `/` which would match everything.
|
|
149
165
|
|
|
150
|
-
|
|
151
|
-
|
|
|
152
|
-
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
| end | boolean | If `true`, only considers the link to be active when the curent location matches the `href` exactly; if `false`, check if the current location _starts with_ `href` |
|
|
166
|
+
| prop | type | description |
|
|
167
|
+
| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
168
|
+
| href | string | The path of the route to navigate to. This will be resolved relative to the route that the link is in, but you can preface it with `/` to refer back to the root. |
|
|
169
|
+
| noScroll | boolean | If true, turn off the default behavior of scrolling to the top of the new page |
|
|
170
|
+
| replace | boolean | If true, don't add a new entry to the browser history. (By default, the new page will be added to the browser history, so pressing the back button will take you to the previous route.) |
|
|
171
|
+
| state | unknown | [Push this value](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) to the history stack when navigating |
|
|
172
|
+
| inactiveClass | string | The class to show when the link is inactive (when the current location doesn't match the link) |
|
|
173
|
+
| activeClass | string | The class to show when the link is active |
|
|
174
|
+
| end | boolean | If `true`, only considers the link to be active when the curent location matches the `href` exactly; if `false`, check if the current location _starts with_ `href` |
|
|
160
175
|
|
|
161
176
|
### The Navigate Component
|
|
177
|
+
|
|
162
178
|
Solid Router provides a `Navigate` component that works similarly to `A`, but it will _immediately_ navigate to the provided path as soon as the component is rendered. It also uses the `href` prop, but you have the additional option of passing a function to `href` that returns a path to navigate to:
|
|
163
179
|
|
|
164
180
|
```jsx
|
|
165
|
-
function getPath
|
|
166
|
-
//navigate is the result of calling useNavigate(); location is the result of calling useLocation().
|
|
167
|
-
//You can use those to dynamically determine a path to navigate to
|
|
181
|
+
function getPath({ navigate, location }) {
|
|
182
|
+
// navigate is the result of calling useNavigate(); location is the result of calling useLocation().
|
|
183
|
+
// You can use those to dynamically determine a path to navigate to
|
|
168
184
|
return "/some-path";
|
|
169
185
|
}
|
|
170
186
|
|
|
171
|
-
//Navigating to /redirect will redirect you to the result of getPath
|
|
172
|
-
<Route path="/redirect" element={<Navigate href={getPath}/>}
|
|
187
|
+
// Navigating to /redirect will redirect you to the result of getPath
|
|
188
|
+
<Route path="/redirect" element={<Navigate href={getPath} />} />;
|
|
173
189
|
```
|
|
174
190
|
|
|
175
191
|
## Dynamic Routes
|
|
@@ -178,27 +194,38 @@ If you don't know the path ahead of time, you might want to treat part of the pa
|
|
|
178
194
|
|
|
179
195
|
```jsx
|
|
180
196
|
import { lazy } from "solid-js";
|
|
181
|
-
import { Routes, Route } from "@solidjs/router"
|
|
197
|
+
import { Routes, Route } from "@solidjs/router";
|
|
182
198
|
const Users = lazy(() => import("./pages/Users"));
|
|
183
199
|
const User = lazy(() => import("./pages/User"));
|
|
184
200
|
const Home = lazy(() => import("./pages/Home"));
|
|
185
201
|
|
|
186
202
|
export default function App() {
|
|
187
|
-
return
|
|
203
|
+
return (
|
|
204
|
+
<>
|
|
188
205
|
<h1>My Site with Lots of Pages</h1>
|
|
189
206
|
<Routes>
|
|
190
207
|
<Route path="/users" component={Users} />
|
|
191
208
|
<Route path="/users/:id" component={User} />
|
|
192
209
|
<Route path="/" component={Home} />
|
|
193
|
-
<Route
|
|
210
|
+
<Route
|
|
211
|
+
path="/about"
|
|
212
|
+
element={<div>This site was made with Solid</div>}
|
|
213
|
+
/>
|
|
194
214
|
</Routes>
|
|
195
215
|
</>
|
|
216
|
+
);
|
|
196
217
|
}
|
|
197
218
|
```
|
|
198
219
|
|
|
199
220
|
The colon indicates that `id` can be any string, and as long as the URL fits that pattern, the `User` component will show.
|
|
200
221
|
|
|
201
|
-
You can then access that `id` from within a route component with `useParams
|
|
222
|
+
You can then access that `id` from within a route component with `useParams`.
|
|
223
|
+
|
|
224
|
+
> **Note on Animation/Transitions**:
|
|
225
|
+
> Routes that share the same path match will be treated as the same route. If you want to force re-render you can wrap your component in a keyed `<Show>` like:
|
|
226
|
+
> ```js
|
|
227
|
+
><Show when={params.something} keyed><MyComponent></Show>
|
|
228
|
+
>```
|
|
202
229
|
|
|
203
230
|
---
|
|
204
231
|
|
|
@@ -206,27 +233,33 @@ Each path parameter can be validated using a `MatchFilter`.
|
|
|
206
233
|
This allows for more complex routing descriptions than just checking the presence of a parameter.
|
|
207
234
|
|
|
208
235
|
```tsx
|
|
209
|
-
import {lazy} from "solid-js";
|
|
210
|
-
import {Routes, Route} from "@solidjs/router"
|
|
211
|
-
import type {SegmentValidators} from "./types";
|
|
236
|
+
import { lazy } from "solid-js";
|
|
237
|
+
import { Routes, Route } from "@solidjs/router";
|
|
238
|
+
import type { SegmentValidators } from "./types";
|
|
212
239
|
|
|
213
240
|
const Users = lazy(() => import("./pages/Users"));
|
|
214
241
|
const User = lazy(() => import("./pages/User"));
|
|
215
242
|
const Home = lazy(() => import("./pages/Home"));
|
|
216
243
|
|
|
217
244
|
const filters: MatchFilters = {
|
|
218
|
-
parent: [
|
|
245
|
+
parent: ["mom", "dad"], // allow enum values
|
|
219
246
|
id: /^\d+$/, // only allow numbers
|
|
220
|
-
withHtmlExtension: (v: string) => v.length > 5 && v.endsWith(
|
|
221
|
-
}
|
|
247
|
+
withHtmlExtension: (v: string) => v.length > 5 && v.endsWith(".html"), // we want an `*.html` extension
|
|
248
|
+
};
|
|
222
249
|
|
|
223
250
|
export default function App() {
|
|
224
|
-
return
|
|
251
|
+
return (
|
|
252
|
+
<>
|
|
225
253
|
<h1>My Site with Lots of Pages</h1>
|
|
226
254
|
<Routes>
|
|
227
|
-
|
|
255
|
+
<Route
|
|
256
|
+
path="/users/:parent/:id/:withHtmlExtension"
|
|
257
|
+
component={User}
|
|
258
|
+
matchFilters={filters}
|
|
259
|
+
/>
|
|
228
260
|
</Routes>
|
|
229
261
|
</>
|
|
262
|
+
);
|
|
230
263
|
}
|
|
231
264
|
```
|
|
232
265
|
|
|
@@ -244,11 +277,10 @@ So in this example:
|
|
|
244
277
|
---
|
|
245
278
|
|
|
246
279
|
```jsx
|
|
247
|
-
//async fetching function
|
|
280
|
+
// async fetching function
|
|
248
281
|
import { fetchUser } ...
|
|
249
282
|
|
|
250
283
|
export default function User () {
|
|
251
|
-
|
|
252
284
|
const params = useParams();
|
|
253
285
|
|
|
254
286
|
const [userData] = createResource(() => params.id, fetchUser);
|
|
@@ -262,8 +294,8 @@ export default function User () {
|
|
|
262
294
|
Parameters can be specified as optional by adding a question mark to the end of the parameter name:
|
|
263
295
|
|
|
264
296
|
```jsx
|
|
265
|
-
//Matches stories and stories/123 but not stories/123/comments
|
|
266
|
-
<Route path=
|
|
297
|
+
// Matches stories and stories/123 but not stories/123/comments
|
|
298
|
+
<Route path="/stories/:id?" element={<Stories />} />
|
|
267
299
|
```
|
|
268
300
|
|
|
269
301
|
### Wildcard Routes
|
|
@@ -271,14 +303,14 @@ Parameters can be specified as optional by adding a question mark to the end of
|
|
|
271
303
|
`:param` lets you match an arbitrary name at that point in the path. You can use `*` to match any end of the path:
|
|
272
304
|
|
|
273
305
|
```jsx
|
|
274
|
-
//Matches any path that begins with foo, including foo/, foo/a/, foo/a/b/c
|
|
275
|
-
<Route path=
|
|
306
|
+
// Matches any path that begins with foo, including foo/, foo/a/, foo/a/b/c
|
|
307
|
+
<Route path="foo/*" component={Foo} />
|
|
276
308
|
```
|
|
277
309
|
|
|
278
310
|
If you want to expose the wild part of the path to the component as a parameter, you can name it:
|
|
279
311
|
|
|
280
312
|
```jsx
|
|
281
|
-
<Route path=
|
|
313
|
+
<Route path="foo/*any" element={<div>{useParams().any}</div>} />
|
|
282
314
|
```
|
|
283
315
|
|
|
284
316
|
Note that the wildcard token must be the last part of the path; `foo/*any/bar` won't create any routes.
|
|
@@ -288,11 +320,12 @@ Note that the wildcard token must be the last part of the path; `foo/*any/bar` w
|
|
|
288
320
|
Routes also support defining multiple paths using an array. This allows a route to remain mounted and not rerender when switching between two or more locations that it matches:
|
|
289
321
|
|
|
290
322
|
```jsx
|
|
291
|
-
//Navigating from login to register does not cause the Login component to re-render
|
|
292
|
-
<Route path={["login", "register"]} component={Login}/>
|
|
323
|
+
// Navigating from login to register does not cause the Login component to re-render
|
|
324
|
+
<Route path={["login", "register"]} component={Login} />
|
|
293
325
|
```
|
|
294
326
|
|
|
295
327
|
## Data Functions
|
|
328
|
+
|
|
296
329
|
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.
|
|
297
330
|
|
|
298
331
|
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.
|
|
@@ -304,21 +337,22 @@ import { fetchUser } ...
|
|
|
304
337
|
|
|
305
338
|
const User = lazy(() => import("./pages/users/[id].js"));
|
|
306
339
|
|
|
307
|
-
//Data function
|
|
340
|
+
// Data function
|
|
308
341
|
function UserData({params, location, navigate, data}) {
|
|
309
342
|
const [user] = createResource(() => params.id, fetchUser);
|
|
310
343
|
return user;
|
|
311
344
|
}
|
|
312
345
|
|
|
313
|
-
//Pass it in the route definition
|
|
346
|
+
// Pass it in the route definition
|
|
314
347
|
<Route path="/users/:id" component={User} data={UserData} />;
|
|
315
348
|
```
|
|
316
349
|
|
|
317
350
|
When the route is loaded, the data function is called, and the result can be accessed by calling `useRouteData()` in the route component.
|
|
318
351
|
|
|
319
352
|
```jsx
|
|
320
|
-
//pages/users/[id].js
|
|
321
|
-
import { useRouteData } from
|
|
353
|
+
// pages/users/[id].js
|
|
354
|
+
import { useRouteData } from "@solidjs/router";
|
|
355
|
+
|
|
322
356
|
export default function User() {
|
|
323
357
|
const user = useRouteData();
|
|
324
358
|
return <h1>{user().name}</h1>;
|
|
@@ -327,12 +361,12 @@ export default function User() {
|
|
|
327
361
|
|
|
328
362
|
As its only argument, the data function is passed an object that you can use to access route information:
|
|
329
363
|
|
|
330
|
-
| key
|
|
331
|
-
|
|
332
|
-
| params
|
|
333
|
-
| location
|
|
334
|
-
| navigate | `(to: string, options?: NavigateOptions) => void`
|
|
335
|
-
| data
|
|
364
|
+
| key | type | description |
|
|
365
|
+
| -------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
366
|
+
| params | object | The route parameters (same value as calling `useParams()` inside the route component) |
|
|
367
|
+
| location | `{ pathname, search, hash, query, state, key}` | An object that you can use to get more information about the path (corresponds to [`useLocation()`](#uselocation)) |
|
|
368
|
+
| navigate | `(to: string, options?: NavigateOptions) => void` | A function that you can call to navigate to a different route instead (corresponds to [`useNavigate()`](#usenavigate)) |
|
|
369
|
+
| data | unknown | The data returned by the [parent's](#nested-routes) data function, if any. (Data will pass through any intermediate nesting.) |
|
|
336
370
|
|
|
337
371
|
A common pattern is to export the data function that corresponds to a route in a dedicated `route.data.js` file. This way, the data function can be imported without loading anything else.
|
|
338
372
|
|
|
@@ -348,16 +382,19 @@ const User = lazy(() => import("/pages/users/[id].js"));
|
|
|
348
382
|
```
|
|
349
383
|
|
|
350
384
|
## Nested Routes
|
|
385
|
+
|
|
351
386
|
The following two route definitions have the same result:
|
|
352
387
|
|
|
353
388
|
```jsx
|
|
354
389
|
<Route path="/users/:id" component={User} />
|
|
355
390
|
```
|
|
391
|
+
|
|
356
392
|
```jsx
|
|
357
393
|
<Route path="/users">
|
|
358
394
|
<Route path="/:id" component={User} />
|
|
359
395
|
</Route>
|
|
360
396
|
```
|
|
397
|
+
|
|
361
398
|
`/users/:id` renders the `<User/>` component, and `/users/` is an empty route.
|
|
362
399
|
|
|
363
400
|
Only leaf Route nodes (innermost `Route` components) are given a route. If you want to make the parent its own route, you have to specify it separately:
|
|
@@ -368,11 +405,11 @@ Only leaf Route nodes (innermost `Route` components) are given a route. If you w
|
|
|
368
405
|
<Route path="/:id" component={User} />
|
|
369
406
|
</Route>
|
|
370
407
|
|
|
371
|
-
//This works
|
|
408
|
+
// This works
|
|
372
409
|
<Route path="/users" component={Users} />
|
|
373
410
|
<Route path="/users/:id" component={User} />
|
|
374
411
|
|
|
375
|
-
//This also works
|
|
412
|
+
// This also works
|
|
376
413
|
<Route path="/users">
|
|
377
414
|
<Route path="/" component={Users} />
|
|
378
415
|
<Route path="/:id" component={User} />
|
|
@@ -380,30 +417,48 @@ Only leaf Route nodes (innermost `Route` components) are given a route. If you w
|
|
|
380
417
|
```
|
|
381
418
|
|
|
382
419
|
You can also take advantage of nesting by adding a parent element with an `<Outlet/>`.
|
|
420
|
+
|
|
383
421
|
```jsx
|
|
384
422
|
import { Outlet } from "@solidjs/router";
|
|
385
423
|
|
|
386
|
-
function PageWrapper
|
|
387
|
-
return
|
|
424
|
+
function PageWrapper() {
|
|
425
|
+
return (
|
|
426
|
+
<div>
|
|
388
427
|
<h1> We love our users! </h1>
|
|
389
|
-
|
|
428
|
+
<Outlet />
|
|
390
429
|
<A href="/">Back Home</A>
|
|
391
430
|
</div>
|
|
431
|
+
);
|
|
392
432
|
}
|
|
393
433
|
|
|
394
434
|
<Route path="/users" component={PageWrapper}>
|
|
395
|
-
<Route path="/" component={Users}/>
|
|
435
|
+
<Route path="/" component={Users} />
|
|
396
436
|
<Route path="/:id" component={User} />
|
|
397
|
-
</Route
|
|
437
|
+
</Route>;
|
|
398
438
|
```
|
|
439
|
+
|
|
399
440
|
The routes are still configured the same, but now the route elements will appear inside the parent element where the `<Outlet/>` was declared.
|
|
400
441
|
|
|
401
442
|
You can nest indefinitely - just remember that only leaf nodes will become their own routes. In this example, the only route created is `/layer1/layer2`, and it appears as three nested divs.
|
|
402
443
|
|
|
403
444
|
```jsx
|
|
404
|
-
<Route
|
|
405
|
-
|
|
406
|
-
|
|
445
|
+
<Route
|
|
446
|
+
path="/"
|
|
447
|
+
element={
|
|
448
|
+
<div>
|
|
449
|
+
Onion starts here <Outlet />
|
|
450
|
+
</div>
|
|
451
|
+
}
|
|
452
|
+
>
|
|
453
|
+
<Route
|
|
454
|
+
path="layer1"
|
|
455
|
+
element={
|
|
456
|
+
<div>
|
|
457
|
+
Another layer <Outlet />
|
|
458
|
+
</div>
|
|
459
|
+
}
|
|
460
|
+
>
|
|
461
|
+
<Route path="layer2" element={<div>Innermost layer</div>}></Route>
|
|
407
462
|
</Route>
|
|
408
463
|
</Route>
|
|
409
464
|
```
|
|
@@ -415,9 +470,11 @@ If you declare a `data` function on a parent and a child, the result of the pare
|
|
|
415
470
|
By default, Solid Router uses `location.pathname` as route path. You can simply switch to hash mode through the `source` property on `<Router>` component.
|
|
416
471
|
|
|
417
472
|
```jsx
|
|
418
|
-
import { Router, hashIntegration } from
|
|
473
|
+
import { Router, hashIntegration } from "@solidjs/router";
|
|
419
474
|
|
|
420
|
-
<Router source={hashIntegration()}
|
|
475
|
+
<Router source={hashIntegration()}>
|
|
476
|
+
<App />
|
|
477
|
+
</Router>;
|
|
421
478
|
```
|
|
422
479
|
|
|
423
480
|
## Memory Mode Router
|
|
@@ -425,9 +482,11 @@ import { Router, hashIntegration } from '@solidjs/router'
|
|
|
425
482
|
You can also use memory mode router for testing purpose.
|
|
426
483
|
|
|
427
484
|
```jsx
|
|
428
|
-
import { Router, memoryIntegration } from
|
|
485
|
+
import { Router, memoryIntegration } from "@solidjs/router";
|
|
429
486
|
|
|
430
|
-
<Router source={memoryIntegration()}
|
|
487
|
+
<Router source={memoryIntegration()}>
|
|
488
|
+
<App />
|
|
489
|
+
</Router>;
|
|
431
490
|
```
|
|
432
491
|
|
|
433
492
|
## Config Based Routing
|
|
@@ -442,25 +501,34 @@ import { Router, useRoutes, A } from "@solidjs/router";
|
|
|
442
501
|
const routes = [
|
|
443
502
|
{
|
|
444
503
|
path: "/users",
|
|
445
|
-
component: lazy(() => import("/pages/users.js"))
|
|
504
|
+
component: lazy(() => import("/pages/users.js")),
|
|
446
505
|
},
|
|
447
506
|
{
|
|
448
507
|
path: "/users/:id",
|
|
449
508
|
component: lazy(() => import("/pages/users/[id].js")),
|
|
450
509
|
children: [
|
|
451
|
-
{
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
510
|
+
{
|
|
511
|
+
path: "/",
|
|
512
|
+
component: lazy(() => import("/pages/users/[id]/index.js")),
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
path: "/settings",
|
|
516
|
+
component: lazy(() => import("/pages/users/[id]/settings.js")),
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
path: "/*all",
|
|
520
|
+
component: lazy(() => import("/pages/users/[id]/[...all].js")),
|
|
521
|
+
},
|
|
522
|
+
],
|
|
455
523
|
},
|
|
456
524
|
{
|
|
457
525
|
path: "/",
|
|
458
|
-
component: lazy(() => import("/pages/index.js"))
|
|
526
|
+
component: lazy(() => import("/pages/index.js")),
|
|
459
527
|
},
|
|
460
528
|
{
|
|
461
529
|
path: "/*all",
|
|
462
|
-
component: lazy(() => import("/pages/[...all].js"))
|
|
463
|
-
}
|
|
530
|
+
component: lazy(() => import("/pages/[...all].js")),
|
|
531
|
+
},
|
|
464
532
|
];
|
|
465
533
|
|
|
466
534
|
function App() {
|
|
@@ -488,6 +556,7 @@ render(
|
|
|
488
556
|
document.getElementById("app")
|
|
489
557
|
);
|
|
490
558
|
```
|
|
559
|
+
|
|
491
560
|
## Router Primitives
|
|
492
561
|
|
|
493
562
|
Solid Router provides a number of primitives that read off the Router and Route context.
|
|
@@ -512,7 +581,7 @@ Retrieves method to do navigation. The method accepts a path to navigate to and
|
|
|
512
581
|
- scroll (_boolean_, default `true`): scroll to top after navigation
|
|
513
582
|
- state (_any_, default `undefined`): pass custom state to `location.state`
|
|
514
583
|
|
|
515
|
-
|
|
584
|
+
**Note:** The state is serialized using the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) which does not support all object types.
|
|
516
585
|
|
|
517
586
|
```js
|
|
518
587
|
const navigate = useNavigate();
|
|
@@ -544,7 +613,13 @@ const [searchParams, setSearchParams] = useSearchParams();
|
|
|
544
613
|
return (
|
|
545
614
|
<div>
|
|
546
615
|
<span>Page: {searchParams.page}</span>
|
|
547
|
-
<button
|
|
616
|
+
<button
|
|
617
|
+
onClick={() =>
|
|
618
|
+
setSearchParams({ page: (parseInt(searchParams.page) || 0) + 1 })
|
|
619
|
+
}
|
|
620
|
+
>
|
|
621
|
+
Next Page
|
|
622
|
+
</button>
|
|
548
623
|
</div>
|
|
549
624
|
);
|
|
550
625
|
```
|
|
@@ -591,7 +666,7 @@ Used to define routes via a config object instead of JSX. See [Config Based Rout
|
|
|
591
666
|
|
|
592
667
|
### useBeforeLeave
|
|
593
668
|
|
|
594
|
-
`useBeforeLeave` takes a function that will be called prior to leaving a route.
|
|
669
|
+
`useBeforeLeave` takes a function that will be called prior to leaving a route. The function will be called with:
|
|
595
670
|
|
|
596
671
|
- from (_Location_): current location (before change).
|
|
597
672
|
- to (_string | number_}: path passed to `navigate`.
|
|
@@ -601,6 +676,7 @@ Used to define routes via a config object instead of JSX. See [Config Based Rout
|
|
|
601
676
|
- retry (_void function_, _force?: boolean_ ): call to retry the same navigation, perhaps after confirming with the user. Pass `true` to skip running the leave handlers again (ie force navigate without confirming).
|
|
602
677
|
|
|
603
678
|
Example usage:
|
|
679
|
+
|
|
604
680
|
```js
|
|
605
681
|
useBeforeLeave((e: BeforeLeaveEventArgs) => {
|
|
606
682
|
if (form.isDirty && !e.defaultPrevented) {
|
|
@@ -615,3 +691,26 @@ useBeforeLeave((e: BeforeLeaveEventArgs) => {
|
|
|
615
691
|
}
|
|
616
692
|
});
|
|
617
693
|
```
|
|
694
|
+
|
|
695
|
+
## SPAs in Deployed Environments
|
|
696
|
+
|
|
697
|
+
When deploying applications that use a client side router that does not rely on Server Side Rendering you need to handle redirects to your index page so that loading from other URLs does not cause your CDN or Hosting to return not found for pages that aren't actually there.
|
|
698
|
+
|
|
699
|
+
Each provider has a different way of doing this. For example on Netlify you create a `_redirects` file that contains:
|
|
700
|
+
|
|
701
|
+
```sh
|
|
702
|
+
/* /index.html 200
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
On Vercel you add a rewrites section to your `vercel.json`:
|
|
706
|
+
|
|
707
|
+
```json
|
|
708
|
+
{
|
|
709
|
+
"rewrites": [
|
|
710
|
+
{
|
|
711
|
+
"source": "/(.*)",
|
|
712
|
+
"destination": "/index.html"
|
|
713
|
+
}
|
|
714
|
+
]
|
|
715
|
+
}
|
|
716
|
+
```
|
package/dist/components.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface RoutesProps {
|
|
|
28
28
|
children: JSX.Element;
|
|
29
29
|
}
|
|
30
30
|
export declare const Routes: (props: RoutesProps) => JSX.Element;
|
|
31
|
-
export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[]
|
|
31
|
+
export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[] | Readonly<RouteDefinition[]>, base?: string) => () => JSX.Element;
|
|
32
32
|
export type RouteProps<S extends string> = {
|
|
33
33
|
path: S | S[];
|
|
34
34
|
children?: JSX.Element;
|
|
@@ -46,12 +46,12 @@ export declare const Route: <S extends string>(props: RouteProps<S>) => JSX.Elem
|
|
|
46
46
|
export declare const Outlet: () => JSX.Element;
|
|
47
47
|
export interface AnchorProps extends Omit<JSX.AnchorHTMLAttributes<HTMLAnchorElement>, "state"> {
|
|
48
48
|
href: string;
|
|
49
|
-
replace?: boolean;
|
|
50
|
-
noScroll?: boolean;
|
|
51
|
-
state?: unknown;
|
|
52
|
-
inactiveClass?: string;
|
|
53
|
-
activeClass?: string;
|
|
54
|
-
end?: boolean;
|
|
49
|
+
replace?: boolean | undefined;
|
|
50
|
+
noScroll?: boolean | undefined;
|
|
51
|
+
state?: unknown | undefined;
|
|
52
|
+
inactiveClass?: string | undefined;
|
|
53
|
+
activeClass?: string | undefined;
|
|
54
|
+
end?: boolean | undefined;
|
|
55
55
|
}
|
|
56
56
|
export declare function A(props: AnchorProps): JSX.Element;
|
|
57
57
|
export { A as Link, A as NavLink, AnchorProps as LinkProps, AnchorProps as NavLinkProps };
|
package/dist/components.jsx
CHANGED
|
@@ -78,8 +78,8 @@ export const Route = (props) => {
|
|
|
78
78
|
};
|
|
79
79
|
export const Outlet = () => {
|
|
80
80
|
const route = useRoute();
|
|
81
|
-
return (<Show when={route.child}>
|
|
82
|
-
{
|
|
81
|
+
return (<Show when={route.child} keyed>
|
|
82
|
+
{child => <RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>}
|
|
83
83
|
</Show>);
|
|
84
84
|
};
|
|
85
85
|
export function A(props) {
|
package/dist/index.js
CHANGED
|
@@ -382,8 +382,8 @@ const useSearchParams = () => {
|
|
|
382
382
|
const location = useLocation();
|
|
383
383
|
const navigate = useNavigate();
|
|
384
384
|
const setSearchParams = (params, options) => {
|
|
385
|
-
const searchString = untrack(() => mergeSearchString(location.search, params));
|
|
386
|
-
navigate(
|
|
385
|
+
const searchString = untrack(() => location.pathname + mergeSearchString(location.search, params) + location.hash);
|
|
386
|
+
navigate(searchString, {
|
|
387
387
|
scroll: false,
|
|
388
388
|
resolve: false,
|
|
389
389
|
...options
|
|
@@ -865,6 +865,7 @@ const Outlet = () => {
|
|
|
865
865
|
get when() {
|
|
866
866
|
return route.child;
|
|
867
867
|
},
|
|
868
|
+
keyed: true,
|
|
868
869
|
children: child => createComponent$1(RouteContextObj.Provider, {
|
|
869
870
|
value: child,
|
|
870
871
|
get children() {
|
package/dist/routing.js
CHANGED
|
@@ -40,8 +40,8 @@ export const useSearchParams = () => {
|
|
|
40
40
|
const location = useLocation();
|
|
41
41
|
const navigate = useNavigate();
|
|
42
42
|
const setSearchParams = (params, options) => {
|
|
43
|
-
const searchString = untrack(() => mergeSearchString(location.search, params));
|
|
44
|
-
navigate(
|
|
43
|
+
const searchString = untrack(() => location.pathname + mergeSearchString(location.search, params) + location.hash);
|
|
44
|
+
navigate(searchString, {
|
|
45
45
|
scroll: false,
|
|
46
46
|
resolve: false,
|
|
47
47
|
...options
|
package/dist/types.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface RouterIntegration {
|
|
|
34
34
|
utils?: Partial<RouterUtils>;
|
|
35
35
|
}
|
|
36
36
|
export interface RouteDataFuncArgs<T = unknown> {
|
|
37
|
-
data: T extends RouteDataFunc
|
|
37
|
+
data: T extends RouteDataFunc<infer _, infer R> ? R : T;
|
|
38
38
|
params: Params;
|
|
39
39
|
location: Location;
|
|
40
40
|
navigate: Navigator;
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"Ryan Turnquist"
|
|
7
7
|
],
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "0.8.
|
|
9
|
+
"version": "0.8.3",
|
|
10
10
|
"homepage": "https://github.com/solidjs/solid-router#readme",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"prettier": "^2.7.1",
|
|
44
44
|
"rollup": "^3.7.5",
|
|
45
45
|
"solid-jest": "^0.2.0",
|
|
46
|
-
"solid-js": "^1.
|
|
46
|
+
"solid-js": "^1.7.9",
|
|
47
47
|
"typescript": "^4.9.4"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|