Skip to content

Commit e9d0891

Browse files
committed
Update
1 parent f3c6bd0 commit e9d0891

File tree

1 file changed

+104
-168
lines changed
  • src/routes/solid-router/reference/data-apis

1 file changed

+104
-168
lines changed

src/routes/solid-router/reference/data-apis/action.mdx

Lines changed: 104 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -2,196 +2,132 @@
22
title: action
33
---
44

5-
Actions are data mutations that can trigger invalidations and further routing.
6-
A list of prebuilt response helpers can be found below.
7-
8-
```jsx
9-
import { action, revalidate, redirect } from "@solidjs/router"
10-
11-
// anywhere
12-
const myAction = action(async (data) => {
13-
await doMutation(data);
14-
throw redirect("/", { revalidate: getUser.keyFor(data.id) }); // throw a response to do a redirect
5+
The `action` function wraps an asynchronous function and returns an action.
6+
Actions enable data mutations and side effects, often in response to user interactions such as form submissions.
7+
To learn more about actions, see [the actions documentation](/solid-router/concepts/actions).
8+
9+
```tsx
10+
import { action } from "@solidjs/router";
11+
12+
const addTodoAction = action(async (name: string) => {
13+
await fetch("https://api.com/todos", {
14+
method: "POST",
15+
body: JSON.stringify({ name }),
16+
});
1517
});
16-
17-
// in component
18-
<form action={myAction} method="post" />
19-
20-
//or
21-
<button type="submit" formaction={myAction}></button>
22-
2318
```
2419

25-
Actions only work with **post** requests.
26-
This means forms require `method="post"`.
27-
28-
A `with` method can be used when typed data is required.
29-
This removes the need to use `FormData` or other additional hidden fields.
30-
The `with` method works similar to [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind), which applies the arguments in order.
20+
## Forms
3121

32-
Without `with`:
22+
Actions can be used to handle form submissions by passing them to the `action` prop in the [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/form) element.
23+
The form values will be accessible through the first parameter of the action function, which is a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object.
3324

34-
```jsx
35-
const deleteTodo = action(async (formData: FormData) => {
36-
const id = Number(formData.get("id"))
37-
await api.deleteTodo(id)
38-
})
25+
Please note that the `<form>` element **must** have `method="post"`.
26+
When using Server-Side Rendering (SSR), you must provide a unique name as the second parameter to the action function.
3927

40-
<form action={deleteTodo} method="post">
41-
<input type="hidden" name="id" value={todo.id} />
42-
<button type="submit">Delete</button>
43-
</form>
28+
```tsx
29+
import { action } from "@solidjs/router";
4430

45-
```
46-
47-
Using `with`:
48-
49-
```jsx del={5,6} ins={7}
50-
const deleteTodo = action(async (id: number) => {
51-
await api.deleteTodo(id)
52-
})
53-
54-
<form action={deleteTodo} method="post">
55-
<input type="hidden" name="id" value={todo.id} />
56-
<form action={deleteTodo.with(todo.id)} method="post">
57-
<button type="submit">Delete</button>
58-
</form>
59-
60-
```
61-
62-
:::tip
63-
In [SolidStart](/solid-start) apps, it's recommended to use the [`"use server"`](/solid-start/reference/server/use-server) directive to leverage server-side caching.
64-
:::
65-
66-
## Notes of `<form>` implementation and SSR
67-
68-
This requires stable references because a string can only be serialized as an attribute, and it is crucial for consistency across SSR. where these references must align.
69-
The solution is to provide a unique name.
70-
71-
```jsx
72-
const myAction = action(async (args) => {}, "my-action");
73-
```
74-
75-
## `useAction`
76-
77-
Instead of forms, actions can directly be wrapped in a `useAction` primitive.
78-
This is how router context is created.
79-
80-
```jsx
81-
// in component
82-
const submit = useAction(myAction);
83-
submit(...args);
31+
const addTodoAction = action(async (formData: FormData) => {
32+
const name = formData.get("name")?.toString();
33+
await fetch("https://api.com/todos", {
34+
method: "POST",
35+
body: JSON.stringify({ name }),
36+
});
37+
}, "add-todo");
8438

39+
function TodoForm() {
40+
return (
41+
<form action={addTodoAction} method="post">
42+
<input name="name" />
43+
<button>Add todo</button>
44+
</form>
45+
);
46+
}
8547
```
8648

87-
The outside of a form context can use custom data instead of `formData`.
88-
These helpers preserve types.
49+
### The `with` method
8950

90-
However, even when used with server functions, such as with [SolidStart](https://start.solidjs.com/getting-started/what-is-solidstart), this requires client-side JavaScript and is not progressively enhanceable like forms are.
51+
Actions have a `with` method that is used to pass additional arguments to the action.
52+
The parameters passed to the `with` method are forwarded to the action function in the same order.
53+
The `FormData` is still available as the last parameter.
9154

92-
## `useSubmission`/`useSubmissions`
55+
```tsx
56+
import { action } from "@solidjs/router";
9357

94-
These functions are used when incorporating optimistic updates during ongoing actions.
95-
They provide either a singular Submission (the latest one), or a collection of Submissions that match, with an optional filtering function.
58+
const addTodoAction = action(async (userId: number, formData: FormData) => {
59+
const name = formData.get("name")?.toString();
60+
await fetch("https://api.com/todos", {
61+
method: "POST",
62+
body: JSON.stringify({ userId, name }),
63+
});
64+
});
9665

97-
```jsx
98-
type Submission<T, U> = {
99-
input: T;
100-
result: U;
101-
error: any;
102-
pending: boolean
103-
clear: () => {}
104-
retry: () => {}
66+
function TodoForm() {
67+
const userId = 1;
68+
return (
69+
<form action={addTodoAction.with(userId)} method="post">
70+
<input name="name" />
71+
<button>Add todo</button>
72+
</form>
73+
);
10574
}
106-
107-
const submissions = useSubmissions(action, (input) => filter(input));
108-
const submission = useSubmission(action, (input) => filter(input));
109-
110-
```
111-
112-
## Revalidate cached functions
113-
114-
### Revalidate all (default)
115-
By default all cached functions will be revalidated wether the action does not return or return a "normal" response.
116-
117-
```jsx
118-
119-
const deleteTodo = action(async (formData: FormData) => {
120-
const id = Number(formData.get("id"))
121-
await api.deleteTodo(id)
122-
// ...
123-
return new Response("success", { status: 200 });
124-
})
12575
```
12676

127-
### Revalidate specific cached keys
128-
129-
By returning a response with solid-router's `json`, `reload` or `redirect` helpers you can pass a key / keys to the revalidate prop as the second argument of the json response helper.
130-
You can either pass as `string` directly or use the cached functions `key` or `keyFor` props.
131-
132-
```jsx
133-
import { action, json, reload, redirect } from "@solidjs/router"
134-
135-
const deleteTodo = action(async (formData: FormData) => {
136-
const id = Number(formData.get("id"))
137-
await api.deleteTodo(id)
138-
return json(
139-
{ deleted: id },
140-
{ revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]}
141-
)
142-
143-
//or
144-
return reload({ revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]})
145-
146-
//or
147-
return redirect("/", { revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]})
148-
149-
})
150-
77+
## Response helpers
78+
79+
Solid Router provides three response helpers that customize the behavior of the action:
80+
81+
- [`json`](/solid-router/reference/response-helpers/json): Allows returning JSON from the action, which will be accessible as the return value when invoking the action using [`useAction`](/solid-router/reference/data-apis/use-action).
82+
- [`redirect`](/solid-router/reference/response-helpers/redirect): Performs a redirect.
83+
- [`reload`](/solid-router/reference/response-helpers/reload): Revalidates queries.
84+
85+
Response helpers return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object with custom properties recognized by Solid Router.
86+
When a `Response` object is either returned or thrown from an action function, Solid Router handles it automatically.
87+
It's advised not to construct a `Response` object without using response helpers.
88+
89+
```tsx
90+
import { action, redirect, json } from "@solidjs/router";
91+
import { getCurrentUser } from "./auth";
92+
93+
const addTodoAction = action(async (name: string) => {
94+
const user = await getCurrentUser();
95+
if (!user) {
96+
throw redirect("/login");
97+
// Or
98+
// return redirect("/login");
99+
}
100+
101+
const todo = await fetch("https://api.com/todos", {
102+
method: "POST",
103+
body: JSON.stringify({ name }),
104+
}).then((response) => response.json());
105+
throw json({ todo });
106+
// Or
107+
// return json({ todo });
108+
});
151109
```
152110

153-
## Prevent revalidation
154-
To opt out of any revalidation you can pass any `string` to revalidate which is not a key of any cached function.
155-
156-
```jsx
157-
const deleteTodo = action(async (formData: FormData) => {
158-
const id = Number(formData.get("id"))
159-
await api.deleteTodo(id)
160-
// returns a `json` without revalidating the action.
161-
return json(`deleted ${id}`,{ revalidate: "nothing" })
111+
## Query revalidation
162112

163-
// or reload the route without revalidating the request.
164-
return reload({ revalidate: "nothing" })
165-
166-
// or redirect without revalidating
167-
return redirect("/", { revalidate: "nothing" })
168-
})
169-
170-
```
113+
By default, when an action is invoked, all [queries](/solid-router/reference/data-apis/query) used on the same page are automatically revalidated.
114+
This behavior can be customized using the [response helpers](#response-helpers).
171115

172-
### Revalidate without action
116+
Response helpers accept a parameter that allows to specify which query keys to revalidate in an action.
117+
This can be used to disable revalidation for a specific set of queries or to disable it entirely.
173118

174-
Cached functions can also be revalidated by the `revalidate` helper.
175-
176-
```jsx
177-
revalidate([getTodos.key, getTodoByID.keyFor(id)])
119+
```tsx
120+
import { action, reload } from "@solidjs/router";
178121

122+
const addTodoAction = action(async (name: string) => {
123+
await fetch("https://api.com/todos", {
124+
method: "POST",
125+
body: JSON.stringify({ name }),
126+
});
127+
return reload({ revalidate: [] });
128+
// return reload({ revalidate: ["getTodos"] });
129+
});
179130
```
180131

181-
This is also great if you want to set your own "refresh" interval e.g. poll data every 30 seconds.
182-
183-
```jsx
184-
export default function TodoLayout(){
185-
186-
const todos = createAsync(() => getTodos())
187-
188-
onMount(() => {
189-
//30 second polling
190-
const interval = setInterval(() => revalidate(getTodos.key),1000 * 30)
191-
onCleanup(() => clearInterval(interval))
192-
})
193-
194-
// ...
195-
}
196-
197-
```
132+
In this example, the first `reload` completely disables revalidation.
133+
The second return (which is commented out) only revalidates queries with the `getTodos` query key.

0 commit comments

Comments
 (0)