Skip to content

Commit f21bc35

Browse files
atilafassinaLadyBluenotes
authored andcommitted
add docs for solid-router
1 parent 21a3704 commit f21bc35

35 files changed

+1035
-14
lines changed

src/routes/data.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"concepts",
77
"advanced-concepts",
88
"guides",
9-
"configuration"
9+
"configuration",
10+
"solid-router"
1011
]
1112
}

src/routes/quick-start.mdx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ Additionally, we offer a [JavaScript](https://stackblitz.com/github/solidjs/temp
1111
## Creating a Solid application
1212

1313
<Callout title="Prerequisites:">
14-
* Familiarity with the command line
15-
* Install [Node.js](https://nodejs.org/en)
14+
* Familiarity with the command line * Install [Node.js](https://nodejs.org/en)
1615
</Callout>
1716

1817
Solid offers convenient project templates that can help kickstart your development.
@@ -41,11 +40,7 @@ npm install
4140
```
4241
</div>
4342

44-
<div id="yarn">
45-
```bash frame="none"
46-
yarn install
47-
```
48-
</div>
43+
<div id="yarn">```bash frame="none" yarn install ```</div>
4944

5045
<div id="pnpm">
5146
```bash frame="none"
@@ -86,11 +81,7 @@ npm install
8681
```
8782
</div>
8883

89-
<div id="yarn">
90-
```bash frame="none"
91-
bash yarn install
92-
```
93-
</div>
84+
<div id="yarn">```bash frame="none" bash yarn install ```</div>
9485

9586
<div id="pnpm">
9687
```bash frame="none"

src/routes/reference/data.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"reactive-utilities",
1010
"rendering",
1111
"secondary-primitives",
12-
"stores"
12+
"stores",
13+
"solid-router"
1314
]
1415
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
title: cache
3+
---
4+
5+
To prevent duplicate fetching and to trigger handle refetching we provide a cache api. That takes a function and returns the same function.
6+
7+
```jsx
8+
const getUser = cache((id) => {
9+
return (await fetch(`/api/users${id}`)).json()
10+
}, "users") // used as cache key + serialized arguments
11+
```
12+
13+
It is expected that the arguments to the cache function are serializable.
14+
15+
This cache accomplishes the following:
16+
17+
1. It does just deduping on the server for the lifetime of the request.
18+
2. It does preload cache in the browser which lasts 10 seconds. When a route is preloaded on hover or when load is called when entering a route it will make sure to dedupe calls.
19+
3. We have a reactive refetch mechanism based on key. So we can tell routes that aren't new to retrigger on action revalidation.
20+
4. It will serve as a back/forward cache for browser navigation up to 5 mins. Any user based navigation or link click bypasses it. Revalidation or new fetch updates the cache.
21+
22+
Using it with load function might look like:
23+
24+
```js
25+
import { lazy } from "solid-js";
26+
import { Route } from "@solidjs/router";
27+
import { getUser } from ... // the cache function
28+
29+
const User = lazy(() => import("./pages/users/[id].js"));
30+
31+
// load function
32+
function loadUser({params, location}) {
33+
void getUser(params.id)
34+
}
35+
36+
// Pass it in the route definition
37+
<Route path="/users/:id" component={User} load={loadUser} />;
38+
```
39+
40+
Inside your page component you:
41+
42+
```jsx
43+
// pages/users/[id].js
44+
import { getUser } from ... // the cache function
45+
46+
export default function User(props) {
47+
const user = createAsync(() => getUser(props.params.id));
48+
return <h1>{user().name}</h1>;
49+
}
50+
```
51+
52+
Cached function has a few useful methods for getting the key that are useful for invalidation.
53+
54+
```ts
55+
let id = 5;
56+
57+
getUser.key; // returns "users"
58+
getUser.keyFor(id); // returns "users[5]"
59+
```
60+
61+
You can revalidate the cache using the `revalidate` method or you can set `revalidate` keys on your response from your actions. If you pass the whole key it will invalidate all the entries for the cache (ie "users" in the example above). You can also invalidate a single entry by using `keyFor`.
62+
63+
`cache` can be defined anywhere and then used inside your components with:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
title: A
3+
---
4+
5+
Like the `<a>` tag but supports relative paths and active class styling (requires client side JavaScript).
6+
7+
The `<A>` tag 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.
8+
9+
| prop | type | description |
10+
| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
11+
| 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. |
12+
| noScroll | boolean | If true, turn off the default behavior of scrolling to the top of the new page |
13+
| 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.) |
14+
| state | unknown | [Push this value](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) to the history stack when navigating |
15+
| inactiveClass | string | The class to show when the link is inactive (when the current location doesn't match the link) |
16+
| activeClass | string | The class to show when the link is active |
17+
| 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` |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"title": "Components",
3+
"pages": ["router.mdx", "route.mdx", "a.mdx", "navigate.mdx"]
4+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: Navigate
3+
---
4+
5+
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:
6+
7+
```jsx
8+
function getPath({ navigate, location }) {
9+
// navigate is the result of calling useNavigate(); location is the result of calling useLocation().
10+
// You can use those to dynamically determine a path to navigate to
11+
return "/some-path";
12+
}
13+
14+
// Navigating to /redirect will redirect you to the result of getPath
15+
<Route path="/redirect" component={() => <Navigate href={getPath} />} />;
16+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
title: Route
3+
---
4+
5+
The Component for defining Routes:
6+
7+
| prop | type | description |
8+
| ------------ | --------------- | ----------------------------------------------------------------- |
9+
| path | string | Path partial for defining the route segment |
10+
| component | `Component` | Component that will be rendered for the matched segment |
11+
| matchFilters | `MatchFilters` | Additional constraints for matching against the route |
12+
| children | `JSX.Element` | Nested `<Route>` definitions |
13+
| load | `RouteLoadFunc` | Function called during preload or when the route is navigated to. |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
title: Router
3+
---
4+
5+
This is the main Router component for the browser.
6+
7+
| prop | type | description |
8+
| ------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- |
9+
| children | `JSX.Element`, `RouteDefinition`, or `RouteDefinition[]` | The route definitions |
10+
| root | Component | Top level layout component |
11+
| base | string | Base url to use for matching routes |
12+
| actionBase | string | Root url for server actions, default: `/_server` |
13+
| preload | boolean | Enables/disables preloads globally, default: `true` |
14+
| explicitLinks | boolean | Disables all anchors being intercepted and instead requires `<A>`. default: `false` |
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
title: action
3+
---
4+
5+
Actions are data mutations that can trigger invalidations and further routing. A list of prebuilt response helpers can be found below.
6+
7+
```jsx
8+
import { action, revalidate, redirect } from "@solidjs/router"
9+
10+
// anywhere
11+
const myAction = action(async (data) => {
12+
await doMutation(data);
13+
throw redirect("/", { revalidate: getUser.keyFor(data.id) }); // throw a response to do a redirect
14+
});
15+
16+
// in component
17+
<form action={myAction} method="post" />
18+
19+
//or
20+
<button type="submit" formaction={myAction}></button>
21+
```
22+
23+
Actions only work with post requests, so make sure to put `method="post"` on your form.
24+
25+
Sometimes it might be easier to deal with typed data instead of `FormData` and adding additional hidden fields. For that reason Actions have a with method. That works similar to `bind` which applies the arguments in order.
26+
27+
Picture an action that deletes Todo Item:
28+
29+
```js
30+
const deleteTodo = action(async (formData: FormData) => {
31+
const id = Number(formData.get("id"))
32+
await api.deleteTodo(id)
33+
})
34+
35+
<form action={deleteTodo} method="post">
36+
<input type="hidden" name="id" value={todo.id} />
37+
<button type="submit">Delete</button>
38+
</form>
39+
```
40+
41+
Instead with `with` you can write this:
42+
43+
```js
44+
const deleteUser = action(api.deleteTodo)
45+
46+
<form action={deleteTodo.with(todo.id)} method="post">
47+
<button type="submit">Delete</button>
48+
</form>
49+
```
50+
51+
### Notes of `<form>` implementation and SSR
52+
53+
This requires stable references as you can only serialize a string as an attribute, and across SSR they'd need to match. The solution is providing a unique name.
54+
55+
```jsx
56+
const myAction = action(async (args) => {}, "my-action");
57+
```
58+
59+
## `useAction`
60+
61+
Instead of forms you can use actions directly by wrapping them in a `useAction` primitive. This is how we get the router context.
62+
63+
```jsx
64+
// in component
65+
const submit = useAction(myAction);
66+
submit(...args);
67+
```
68+
69+
The outside of a form context you can use custom data instead of formData, and these helpers preserve types. However, even when used with server functions (in projects like SolidStart) this requires client side javascript and is not Progressive Enhancible like forms are.
70+
71+
## `useSubmission`/`useSubmissions`
72+
73+
Are used to injecting the optimistic updates while actions are in flight. They either return a single Submission(latest) or all that match with an optional filter function.
74+
75+
```jsx
76+
type Submission<T, U> = {
77+
input: T;
78+
result: U;
79+
error: any;
80+
pending: boolean
81+
clear: () => {}
82+
retry: () => {}
83+
}
84+
85+
const submissions = useSubmissions(action, (input) => filter(input));
86+
const submission = useSubmission(action, (input) => filter(input));
87+
```

0 commit comments

Comments
 (0)