From 39f3b9f8492aff90e2ae7d4dc0c5195e1b92a5ad Mon Sep 17 00:00:00 2001
From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com>
Date: Fri, 16 May 2025 11:46:09 +0330
Subject: [PATCH 1/6] Fix useSubmission
---
.../reference/data-apis/use-submission.mdx | 202 ++++++------------
1 file changed, 61 insertions(+), 141 deletions(-)
diff --git a/src/routes/solid-router/reference/data-apis/use-submission.mdx b/src/routes/solid-router/reference/data-apis/use-submission.mdx
index 7153e664cd..b4e9f969d0 100644
--- a/src/routes/solid-router/reference/data-apis/use-submission.mdx
+++ b/src/routes/solid-router/reference/data-apis/use-submission.mdx
@@ -2,160 +2,80 @@
title: useSubmission
---
-This helper is used to handle form submissions and can provide optimistic updates while actions are in flight as well as pending state feedback.
-This method will return a single (latest) value while its sibling, [`useSubmissions`](/solid-router/reference/data-apis/use-submissions), will return all values submitted while the component is active. With an optional second parameter for a filter function.
+The `useSubmission` function returns a submission object for a specified action.
+This submission object contains properties to access the state of action execution and functions to control the action.
-It's important to note that `useSubmission` requires the form method to be **post** otherwise it will trigger a browser navigation and will not work.
-
-```tsx title="component.tsx" {4,8}
-import { useSubmission } from "@solidjs/router";
-
-function Component() {
- const submission = useSubmission(postNameAction);
-
- return (
-
- )
+```tsx
+import { Show } from "solid-js";
+import { action, useSubmission } from "@solidjs/router";
+
+const addTodoAction = action(async (formData: FormData) => {
+ const name = formData.get("name")?.toString() ?? "";
+ if (name.length <= 2) {
+ throw new Error("Name must be larger than 2 characters");
+ }
+}, "addTodo");
+
+function AddTodoForm() {
+ const submission = useSubmission(addTodoAction);
+ return (
+
+ );
}
```
-:::note
-Learn more about actions in the [`action`](/solid-router/reference/data-apis/action) docs.
+:::info[Note]
+If an action is executed multiple times, the last submission will be returned.
+To access all submissions, `useSubmissions`[/solid-router/reference/data-apis/use-submissions] can be used.
:::
-## Filtering Submissions
-
-As an optional second parameter, the `useSubmission` helper can receive a filter function to only return the submission that matches the condition.
-The filter receives the submitted dated as a parameter and should return a boolean value.
-E.g.: action below will only submit if the name is "solid".
-
-```tsx title="component.tsx" {4-8}
-import { useSubmission } from "@solidjs/router";
-
-function Component() {
- const submission = useSubmission(postNameAction, ([formData]) => {
- const name = formData.get("name") ?? "";
-
- return name === "solid";
- });
-
- return (
-
- )
-}
-```
-
-## Optimistic Updates
-
-When the form is submitted, the `submission` object will be updated with the new value and the `pending` property will be set to `true`.
-This allows you to provide feedback to the user that the action is in progress.
-Once the action is complete, the `pending` property will be set to `false` and the `result` property will be updated with final value.
-
-```tsx tab title="TypeScript" {6,10-12}
-// component.tsx
-import { Show } from "solid-js";
-import { useSubmission } from "@solidjs/router";
-
-function Component() {
- const submission = useSubmission(postNameAction);
-
- return (
- <>
-
- {(name) =>
Optimistic: {name() as string}
}
-
+## Filter function
-
- {(name) =>
Result: {name()}
}
-
+Optionally, `useSubmission` accepts a second parameter, which is a filter function.
+This function is executed for each submission and returns the first submission that passes through the filter.
+The filter function takes the submitted data as its parameter and should return `true` to select the submission and `false` otherwise.
-
- >
- )
-}
-```
-
-```tsx tab title="JavaScript" {6,10-12}
-// component.jsx
-import { Show } from "solid-js";
+```tsx
import { useSubmission } from "@solidjs/router";
-
-function Component() {
- const submission = useSubmission(postNameAction);
-
- return (
- <>
-
- {(name) =>
;
}
```
-## Error Handling
-
-If the action fails, the `submission` object will be updated with the error and the `pending` property will be set to `false`.
-This allows you to provide feedback to the user that the action has failed. Additionally, the return type of `useSubmission` will have a new key `error` that will contain the error object thrown by the submission handler.
-
-At this stage, you can also use the `retry()` method to attempt the action again or the `clear()` to wipe the filled data in the platform.
+## Parameters
-```tsx title="component.tsx" {12-18}
-import { Show } from "solid-js";
-import { useSubmission } from "@solidjs/router";
+- **action**: The action for which you want to return submissions.
+- **filter** (Optional): The filter function that receives the submitted data as its parameter.
+ It should return `true` if the submission passes the filter and `false` otherwise.
-function Component() {
- const submission = useSubmission(postNameAction);
+## Returns
- return (
- <>
-
- {(error) => (
-
-
Error: {error.message}
-
-
-
- )}
-
+`useSubmission` returns an object containing the following properties:
-
- >
- )
-}
-```
+- **input**: The input data of the action.
+- **result**: The returned value of the action.
+- **error**: Any error thrown from the action.
+- **pending**: A boolean indicating whether the action is currently being executed.
+- **clear**: A function to clear the results of the submission.
+- **retry**: A function to re-execute the action.
From f3c6bd051aafbd65fb5805b7cddb4c6a7ea6a783 Mon Sep 17 00:00:00 2001
From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com>
Date: Sun, 8 Jun 2025 11:42:11 +0330
Subject: [PATCH 2/6] Update
---
.../reference/data-apis/use-submission.mdx | 31 +-
.../reference/data-apis/use-submissions.mdx | 264 ++++++------------
2 files changed, 110 insertions(+), 185 deletions(-)
diff --git a/src/routes/solid-router/reference/data-apis/use-submission.mdx b/src/routes/solid-router/reference/data-apis/use-submission.mdx
index b4e9f969d0..962efa5349 100644
--- a/src/routes/solid-router/reference/data-apis/use-submission.mdx
+++ b/src/routes/solid-router/reference/data-apis/use-submission.mdx
@@ -2,8 +2,7 @@
title: useSubmission
---
-The `useSubmission` function returns a submission object for a specified action.
-This submission object contains properties to access the state of action execution and functions to control the action.
+The `useSubmission` function retrieves the state of the most recent submission for a given action.
```tsx
import { Show } from "solid-js";
@@ -37,15 +36,14 @@ function AddTodoForm() {
```
:::info[Note]
-If an action is executed multiple times, the last submission will be returned.
-To access all submissions, `useSubmissions`[/solid-router/reference/data-apis/use-submissions] can be used.
+To access the state of all submissions, `useSubmissions`[/solid-router/reference/data-apis/use-submissions] can be used.
:::
## Filter function
-Optionally, `useSubmission` accepts a second parameter, which is a filter function.
-This function is executed for each submission and returns the first submission that passes through the filter.
-The filter function takes the submitted data as its parameter and should return `true` to select the submission and `false` otherwise.
+The `useSubmission` function optionally accepts a second parameter, which is a filter function.
+This function is executed for each submission in the order they were created, and the first submission that meet the filter criteria is returned by `useSubmission`.
+The filter function recieves the input data of the action as its parameter and must return `true` to select the submission or `false` otherwise.
```tsx
import { useSubmission } from "@solidjs/router";
@@ -59,23 +57,28 @@ function LatestTodo() {
return name.length > 2;
}
);
- return
;
}
```
## Parameters
-- **action**: The action for which you want to return submissions.
-- **filter** (Optional): The filter function that receives the submitted data as its parameter.
- It should return `true` if the submission passes the filter and `false` otherwise.
+- **action**: The action for which you want to get the most recent submission.
+- **filter** (optional): A filter function.
+ When provided, it executes on each submission in the order of creation, returning the first submission that passes the filter.
+ It receives the input data of the action as its parameter and must return `true` for the submission to be selected and `false` otherwise.
## Returns
`useSubmission` returns an object containing the following properties:
- **input**: The input data of the action.
-- **result**: The returned value of the action.
+ This is a reactive value.
+- **result**: The value returned from the action.
+ This is a reactive value.
- **error**: Any error thrown from the action.
+ This is a reactive value.
- **pending**: A boolean indicating whether the action is currently being executed.
-- **clear**: A function to clear the results of the submission.
-- **retry**: A function to re-execute the action.
+ This is a reactive value.
+- **clear**: A function that clears the result of the submission.
+- **retry**: A function that re-executes the submission with the same input.
diff --git a/src/routes/solid-router/reference/data-apis/use-submissions.mdx b/src/routes/solid-router/reference/data-apis/use-submissions.mdx
index c03ac618ca..e5f10d17ce 100644
--- a/src/routes/solid-router/reference/data-apis/use-submissions.mdx
+++ b/src/routes/solid-router/reference/data-apis/use-submissions.mdx
@@ -2,189 +2,111 @@
title: useSubmissions
---
-This helper is used to handle form submissions and can provide optimistic updates while actions are in flight as well as pending state feedback.
-This method will return an iterable of all submitted actions while its component is mounted. With an optional second parameter for a filter function.
-
-:::tip
-If you only care for the latest submission, you can use the [`useSubmission`](/solid-router/reference/data-apis/use-submission) helper.
-:::
-
-It's important to note that it requires the form method to be **post** otherwise it will trigger a browser navigation and will not work.
-
-In the example below, the `useSubmissions` helper is used to retain a list of all submission results to that action while also giving feedback on the pending state of the current in-flight submission.
-
-```tsx title="component.tsx" {4,9-20, 23}
-import { useSubmissions } from "@solidjs/router";
-
-function Component() {
- const submissions = useSubmissions(postNameAction);
-
- return (
-
- )
+The `useSubmissions` function retrieves the state of all submissions for a given action.
+
+```tsx
+import { For, Show } from "solid-js";
+import { action, useSubmissions } from "@solidjs/router";
+
+const addTodoAction = action(async (formData: FormData) => {
+ const name = formData.get("name")?.toString() ?? "";
+ if (name.length <= 2) {
+ throw new Error("Name must be larger than 2 characters");
+ }
+ return name;
+}, "addTodo");
+
+export default function AddTodoForm() {
+ const submissions = useSubmissions(addTodoAction);
+ return (
+
+ );
}
```
-:::note
-To trigger a submission, [actions](https://docs.solidjs.com/) can be used.
+:::info[Note]
+To access the state of the most recent submission, `useSubmission`[/solid-router/reference/data-apis/use-submission] can be used.
:::
-## Filtering Submissions
+## Filter function
-As an optional second parameter, the `useSubmissions` helper can receive a filter function to only return the submission that matches the condition.
-The filter receives the submitted dated as a parameter and should return a boolean value.
-E.g.: action below will only submit if the name is "solid".
+The `useSubmissions` function optionally accepts a second parameter, which is a filter function.
+This function is executed for each submission in the order they were created, and only the submissions that meet the filter criteria are returned by `useSubmissions`.
+The filter function recieves the input data of the action as its parameter and must return `true` to select the submission or `false` otherwise.
-```tsx title="component.tsx" {4-8}
+```tsx
import { useSubmissions } from "@solidjs/router";
-
-function Component() {
- const submissions = useSubmissions(postNameAction, ([formData]) => {
- const name = formData.get("name") ?? "";
-
- return name === "solid";
- });
-
- return (
-
- )
+import { addTodoAction } from "./actions";
+
+function FailedTodos() {
+ const failedSubmissions = useSubmissions(
+ addTodoAction,
+ ([formData]: [FormData]) => {
+ const name = formData.get("name")?.toString() ?? "";
+ return name.length <= 2;
+ }
+ );
+ return (
+
+ );
}
```
-## Optimistic Updates
-
-When the form is submitted, the `submission` object will be updated with the new value and the `pending` property will be set to `true`.
-This allows you to provide feedback to the user that the action is in progress.
-Once the action is complete, the `pending` property will be set to `false` and the `result` property will be updated with final value.
+## Parameters
-```tsx tab title="TypeScript" {6,13-20}
-// component.tsx
-import { Show } from "solid-js";
-import { useSubmissions } from "@solidjs/router";
-
-function Component() {
- const submissions = useSubmissions(postNameAction);
+- **action**: The action for which you want to get the submissions.
+- **filter** (optional): A filter function.
+ When provided, it executes on each submission in the order of creation, returning the submissions that pass the filter.
+ It receives the input data of the action as its parameter and must return `true` to select the submission and `false` otherwise.
- return (
-
- )
-}
-```
+`useSubmissions` returns an array of submissions.
+Each submission is an object containing the following properties:
-```tsx tab title="JavaScript" {6,13-20}
-// component.jsx
-import { Show } from "solid-js";
-import { useSubmissions } from "@solidjs/router";
-
-function Component() {
- const submissions = useSubmissions(postNameAction);
-
- return (
-
- )
-}
-```
-
-## Error Handling
-
-If the action fails, the `submission` object will be updated with the error and the `pending` property will be set to `false`.
-This allows you to provide feedback to the user that the action has failed. Additionally, the return type of `useSubmission` will have a new key `error` that will contain the error object thrown by the submission handler.
-
-At this stage, you can also use the `retry()` method to attempt the action again or the `clear()` to wipe the filled data in the platform.
-
-```tsx title="component.tsx" {12-18}
-import { Show } from "solid-js";
-import { useSubmissions } from "@solidjs/router";
-
-function Component() {
- const submissions = useSubmissions(postNameAction);
-
- return (
-
- )
-}
-```
+- **input**: The input data of the action.
+ This is a reactive value.
+- **result**: The value returned from the action.
+ This is a reactive value.
+- **error**: Any error thrown from the action.
+ This is a reactive value.
+- **pending**: A boolean indicating whether the action is currently being executed.
+ This is a reactive value.
+- **clear**: A function that clears the result of the submission.
+- **retry**: A function that re-executes the submission with the same input.
From e9d0891209e924de5f9beaa147c352587366075e Mon Sep 17 00:00:00 2001
From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com>
Date: Wed, 11 Jun 2025 18:58:40 +0330
Subject: [PATCH 3/6] Update
---
.../reference/data-apis/action.mdx | 272 +++++++-----------
1 file changed, 104 insertions(+), 168 deletions(-)
diff --git a/src/routes/solid-router/reference/data-apis/action.mdx b/src/routes/solid-router/reference/data-apis/action.mdx
index 8f3a5e666a..5c9f48e580 100644
--- a/src/routes/solid-router/reference/data-apis/action.mdx
+++ b/src/routes/solid-router/reference/data-apis/action.mdx
@@ -2,196 +2,132 @@
title: action
---
-Actions are data mutations that can trigger invalidations and further routing.
-A list of prebuilt response helpers can be found below.
-
-```jsx
-import { action, revalidate, redirect } from "@solidjs/router"
-
-// anywhere
-const myAction = action(async (data) => {
- await doMutation(data);
- throw redirect("/", { revalidate: getUser.keyFor(data.id) }); // throw a response to do a redirect
+The `action` function wraps an asynchronous function and returns an action.
+Actions enable data mutations and side effects, often in response to user interactions such as form submissions.
+To learn more about actions, see [the actions documentation](/solid-router/concepts/actions).
+
+```tsx
+import { action } from "@solidjs/router";
+
+const addTodoAction = action(async (name: string) => {
+ await fetch("https://api.com/todos", {
+ method: "POST",
+ body: JSON.stringify({ name }),
+ });
});
-
-// in component
-
-
-//or
-
-
```
-Actions only work with **post** requests.
-This means forms require `method="post"`.
-
-A `with` method can be used when typed data is required.
-This removes the need to use `FormData` or other additional hidden fields.
-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.
+## Forms
-Without `with`:
+Actions can be used to handle form submissions by passing them to the `action` prop in the [`
+```tsx
+import { action } from "@solidjs/router";
-```
-
-Using `with`:
-
-```jsx del={5,6} ins={7}
-const deleteTodo = action(async (id: number) => {
- await api.deleteTodo(id)
-})
-
-
-
-```
-
-:::tip
-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.
-:::
-
-## Notes of `
+ );
+}
```
-The outside of a form context can use custom data instead of `formData`.
-These helpers preserve types.
+### The `with` method
-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.
+Actions have a `with` method that is used to pass additional arguments to the action.
+The parameters passed to the `with` method are forwarded to the action function in the same order.
+The `FormData` is still available as the last parameter.
-## `useSubmission`/`useSubmissions`
+```tsx
+import { action } from "@solidjs/router";
-These functions are used when incorporating optimistic updates during ongoing actions.
-They provide either a singular Submission (the latest one), or a collection of Submissions that match, with an optional filtering function.
+const addTodoAction = action(async (userId: number, formData: FormData) => {
+ const name = formData.get("name")?.toString();
+ await fetch("https://api.com/todos", {
+ method: "POST",
+ body: JSON.stringify({ userId, name }),
+ });
+});
-```jsx
-type Submission = {
- input: T;
- result: U;
- error: any;
- pending: boolean
- clear: () => {}
- retry: () => {}
+function TodoForm() {
+ const userId = 1;
+ return (
+
+ );
}
-
-const submissions = useSubmissions(action, (input) => filter(input));
-const submission = useSubmission(action, (input) => filter(input));
-
-```
-
-## Revalidate cached functions
-
-### Revalidate all (default)
-By default all cached functions will be revalidated wether the action does not return or return a "normal" response.
-
-```jsx
-
-const deleteTodo = action(async (formData: FormData) => {
- const id = Number(formData.get("id"))
- await api.deleteTodo(id)
- // ...
- return new Response("success", { status: 200 });
-})
```
-### Revalidate specific cached keys
-
-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.
-You can either pass as `string` directly or use the cached functions `key` or `keyFor` props.
-
-```jsx
-import { action, json, reload, redirect } from "@solidjs/router"
-
-const deleteTodo = action(async (formData: FormData) => {
- const id = Number(formData.get("id"))
- await api.deleteTodo(id)
- return json(
- { deleted: id },
- { revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]}
- )
-
- //or
- return reload({ revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]})
-
- //or
- return redirect("/", { revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]})
-
-})
-
+## Response helpers
+
+Solid Router provides three response helpers that customize the behavior of the action:
+
+- [`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).
+- [`redirect`](/solid-router/reference/response-helpers/redirect): Performs a redirect.
+- [`reload`](/solid-router/reference/response-helpers/reload): Revalidates queries.
+
+Response helpers return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object with custom properties recognized by Solid Router.
+When a `Response` object is either returned or thrown from an action function, Solid Router handles it automatically.
+It's advised not to construct a `Response` object without using response helpers.
+
+```tsx
+import { action, redirect, json } from "@solidjs/router";
+import { getCurrentUser } from "./auth";
+
+const addTodoAction = action(async (name: string) => {
+ const user = await getCurrentUser();
+ if (!user) {
+ throw redirect("/login");
+ // Or
+ // return redirect("/login");
+ }
+
+ const todo = await fetch("https://api.com/todos", {
+ method: "POST",
+ body: JSON.stringify({ name }),
+ }).then((response) => response.json());
+ throw json({ todo });
+ // Or
+ // return json({ todo });
+});
```
-## Prevent revalidation
-To opt out of any revalidation you can pass any `string` to revalidate which is not a key of any cached function.
-
-```jsx
-const deleteTodo = action(async (formData: FormData) => {
- const id = Number(formData.get("id"))
- await api.deleteTodo(id)
- // returns a `json` without revalidating the action.
- return json(`deleted ${id}`,{ revalidate: "nothing" })
+## Query revalidation
- // or reload the route without revalidating the request.
- return reload({ revalidate: "nothing" })
-
- // or redirect without revalidating
- return redirect("/", { revalidate: "nothing" })
-})
-
-```
+By default, when an action is invoked, all [queries](/solid-router/reference/data-apis/query) used on the same page are automatically revalidated.
+This behavior can be customized using the [response helpers](#response-helpers).
-### Revalidate without action
+Response helpers accept a parameter that allows to specify which query keys to revalidate in an action.
+This can be used to disable revalidation for a specific set of queries or to disable it entirely.
-Cached functions can also be revalidated by the `revalidate` helper.
-
-```jsx
-revalidate([getTodos.key, getTodoByID.keyFor(id)])
+```tsx
+import { action, reload } from "@solidjs/router";
+const addTodoAction = action(async (name: string) => {
+ await fetch("https://api.com/todos", {
+ method: "POST",
+ body: JSON.stringify({ name }),
+ });
+ return reload({ revalidate: [] });
+ // return reload({ revalidate: ["getTodos"] });
+});
```
-This is also great if you want to set your own "refresh" interval e.g. poll data every 30 seconds.
-
-```jsx
-export default function TodoLayout(){
-
- const todos = createAsync(() => getTodos())
-
- onMount(() => {
- //30 second polling
- const interval = setInterval(() => revalidate(getTodos.key),1000 * 30)
- onCleanup(() => clearInterval(interval))
- })
-
- // ...
-}
-
-```
+In this example, the first `reload` completely disables revalidation.
+The second return (which is commented out) only revalidates queries with the `getTodos` query key.
From 5a7ec5c489031915c4455d88f99600769446119c Mon Sep 17 00:00:00 2001
From: Amir Hossein Hashemi <87268103+amirhhashemi@users.noreply.github.com>
Date: Thu, 19 Jun 2025 01:20:19 +0330
Subject: [PATCH 4/6] Update info callout titles (#1207)
---
.../solid-router/reference/data-apis/use-submission.mdx | 2 +-
src/ui/callout.tsx | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/routes/solid-router/reference/data-apis/use-submission.mdx b/src/routes/solid-router/reference/data-apis/use-submission.mdx
index 962efa5349..4c2055bcbc 100644
--- a/src/routes/solid-router/reference/data-apis/use-submission.mdx
+++ b/src/routes/solid-router/reference/data-apis/use-submission.mdx
@@ -35,7 +35,7 @@ function AddTodoForm() {
}
```
-:::info[Note]
+:::note
To access the state of all submissions, `useSubmissions`[/solid-router/reference/data-apis/use-submissions] can be used.
:::
diff --git a/src/ui/callout.tsx b/src/ui/callout.tsx
index 9878c4266a..a69862a883 100644
--- a/src/ui/callout.tsx
+++ b/src/ui/callout.tsx
@@ -101,7 +101,11 @@ export function Callout(props: CalloutProps) {
+=======
+
+>>>>>>> 0c3b40b1 (Update info callout titles (#1207))
{props.type || "Note"}
}
From aec869e9c7b82496f08c274032ce3fe8c99085ff Mon Sep 17 00:00:00 2001
From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com>
Date: Wed, 2 Jul 2025 07:38:29 +0330
Subject: [PATCH 5/6] update
---
src/routes/solid-router/concepts/actions.mdx | 231 ++++++++++--------
.../reference/data-apis/use-submission.mdx | 2 +-
.../reference/data-apis/use-submissions.mdx | 4 +-
3 files changed, 126 insertions(+), 111 deletions(-)
diff --git a/src/routes/solid-router/concepts/actions.mdx b/src/routes/solid-router/concepts/actions.mdx
index 53a96da9c5..0f8af92cef 100644
--- a/src/routes/solid-router/concepts/actions.mdx
+++ b/src/routes/solid-router/concepts/actions.mdx
@@ -2,151 +2,166 @@
title: "Actions"
---
-When developing applications, it is common to need to communicate new information to the server based on user interactions.
-Actions are Solid Router’s solution to this problem.
+Actions provide a powerful and flexible mechanism for handling data mutations and side effects.
+They are designed to simplify your application's data flow, ensure a consistent user experience, and integrate seamlessly with Solid's reactivity.
-## What are actions?
+Actions provide several key benefits:
-Actions are asynchronous processing functions that allow you to submit data to your server and receive a response.
-They are isomorphic, meaning they can run either on the server or the client, depending on what is needed.
-This flexibility makes actions a powerful tool for managing and tracking data submissions.
-
-### How actions work
-
-Actions represent the server-side part of an [HTML form](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form).
-They handle submissions through POST requests, allowing you to easily use HTML forms to send data.
-
-When a user performs an action, such as submitting a form, the data is sent to the server for processing via an action.
-
-### Benefits of using actions
-
-1. **Isomorphic**: Since actions can run on both the server and client, you can optimize performance by choosing the best execution environment for your needs.
-2. **Asynchronous processing**: Actions handle data submissions asynchronously, ensuring that your application remains responsive.
-3. **Simplified data handling**: By using actions, the process of managing and tracking data submissions can be streamlined, reducing the complexity of your application.
+- **Centralized Logic**: Encapsulate the logic for data modifications in a single, reusable function.
+- **Integrated State Management**: Solid Router automatically tracks the execution state of an action (whether it's pending, successful, or has encountered an error), making it easy to build reactive UI feedback.
+- **Automatic Data Revalidation**: By default, after an action successfully completes, Solid Router revalidates any queries on the same page.
+ This ensures your UI reflects the latest data without manual intervention.
+- **Progressive Enhancement**: When used with HTML forms, actions can enable forms to function even if JavaScript is not yet loaded, providing a robust and accessible user experience.
## Creating actions
-To create an action, use the `action` function from the `@solidjs/router` package.
-This function takes an asynchronous function as an argument and returns a new function that can be used to submit data.
+At their core, actions are **asynchronous functions** that you define using the `action` function.
+The [`action`](/solid-router/reference/data-apis/action) function takes your asynchronous function and returns an action object.
+
+To define an action, import the `action` function from `@solidjs/router` and pass it your asynchronous logic:
```tsx
import { action } from "@solidjs/router";
-const echo = action(async (message: string) => {
- // Simulates an asynchronous operation, such as an API call
- await new Promise((resolve, reject) => setTimeout(resolve, 1000));
- console.log(message);
+const addPostAction = action(async (title: string) => {
+ const response = await fetch("https://api.com/posts", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ title }),
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json();
+ throw new Error(errorData.message || "Failed to add post");
+ }
+
+ return await response.json();
});
```
-In this example, the `echo` action simulates a fetch call with a 1 second delay before logging the message to the console.
-The `echo` action will act as a backend, however, it can be substituted for any API provided it can be run on the client.
-Typically, route actions are used with some sort of solution like fetch or GraphQL.
+In this example, `addPostAction` handles sending a POST request to create a new post.
+The return value of the action can be accessed later when tracking action state.
-:::tip
-In [SolidStart](/solid-start) apps, it's recommended to use the [`"use server"`](/solid-start/reference/server/use-server) directive to leverage server-side functionality.
+:::note[Server-Side Rendering (SSR)]
+When using actions with SSR, you must provide a unique name string as the second parameter to the `action` function.
+This is crucial for Solid Router to correctly identify and re-run actions on the server.
+We'll explore this in more detail in the Handling Form Submissions section.
:::
-### Using actions
-
-To use the action, you can call it from within a component using [`useAction`](/solid-router/reference/data-apis/use-action).
-This returns a function that can be called with the necessary arguments to trigger the action.
-
-```tsx del={1} ins={2,9-13}
-import { action } from "@solidjs/router";
-import { action, useAction } from "@solidjs/router";
-
-const echo = action(async (message: string) => {
- await new Promise((resolve, reject) => setTimeout(resolve, 1000));
- console.log(message);
-});
-
-export function MyComponent() {
- const myEcho = useAction(echo);
-
- myEcho("Hello from Solid!");
-}
-```
-
-In this component, `useAction` is used to get a reference to the `echo` action.
-The action is then called with the message `"Hello from Solid!"`, which will be logged to the console after a 1 second delay.
-
-### Returning data from actions
+## How to Use Actions
-In many cases, after submitting data, the server sends some data back as well.
-This may be in the form of an error message if something has failed or the results of a successful operation.
-Anything returned from an action can be accessed using the reactive `action.result` property, where the value can change each time you submit your action.
+Solid Router offers two primary ways to invoke an action:
-To access the action's result, you must pass the action to `useSubmission`:
+1. **Via the `
+ );
}
```
-Using `useSubmission` leaves the implementation details of how you trigger `echo` up to you.
-When handling user inputs, for example, it is better to use a `form` for a multitude of reasons.
+When this form is submitted, `addPostFormAction` will be invoked with the `FormData` containing the form values.
-## Using forms to submit data
+:::tip[File Uploads]
-When submitting data with actions, it is recommended to use HTML forms.
-These forms can be used prior to JavaScript loading, which creates instantly interactive applications.
-This also inherently provides accessibility benefits, saving the time of designing a custom UI library that may not have these benefits.
+If your form includes file inputs, ensure your
+```
-If you do not return a `Response` from your action, the user will stay on the same page and responses will be re-triggered.
-Using a `redirect` can tell the browser to navigate to a new page.
+:::
+#### Passing additional data
-```tsx
-import { action, redirect } from "@solidjs/router";
+Sometimes, your action might need additional data that isn't part of the form's inputs.
+You can pass these additional arguments using the `with` method on your action.
-const isAdmin = action(async (formData: FormData) => {
- await new Promise((resolve, reject) => setTimeout(resolve, 1000));
+Arguments passed to `with` will be forwarded to your action function before the `FormData` object.
- const username = formData.get("username");
+```tsx
+import { action } from "@solidjs/router";
- if (username === "admin") throw redirect("/admin");
- return new Error("Invalid username");
+const updatePostAction = action(async (postId: string, formData: FormData) => {
+ const newTitle = formData.get("title")?.toString();
+
+ if (!newTitle || newTitle.trim() === "") {
+ throw new Error("Post title cannot be empty.");
+ }
+
+ const response = await fetch(
+ `https://api.com/posts/${encodeURIComponent(newTitle)}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ title: newTitle }),
+ }
+ );
+
+ if (!response.ok) {
+ const errorData = await response.json();
+ throw new Error(errorData.message || "Failed to update post");
+ }
});
-export function MyComponent() {
-
- return (
-
- );
+function PostEditForm(props: { postId: string }) {
+ return (
+
+ );
}
```
-**Note:** If you are uploading files make sure you include `enctype="multipart/form-data"` to your `
+
+
+
+
+
+
+ {(error) => (
+
+
Error: {error().message}
+
+
+
+ )}
+
+
+ {(result) => (
+
{result().message}
+ )}
+
+
+ );
+}
+```
+
+In this example, the form's submit button is disabled during `submission.pending`, and appropriate messages are shown based on `submission.error` or `submission.result`.
+The `clear` method resets the submission state, and `retry` re-executes the last submission with its original input.
+
+For more details, see the [`useSubmission` API reference](/solid-router/reference/data-apis/use-submission).
+
+:::tip
+If you need to track multiple concurrent or recent submissions for an action (e.g., a list of file uploads, a queue of items being processed), the [`useSubmissions` primitive](/solid-router/reference/data-apis/use-submissions) can be used.
+:::
diff --git a/src/ui/callout.tsx b/src/ui/callout.tsx
index a69862a883..9878c4266a 100644
--- a/src/ui/callout.tsx
+++ b/src/ui/callout.tsx
@@ -101,11 +101,7 @@ export function Callout(props: CalloutProps) {
-=======
-
->>>>>>> 0c3b40b1 (Update info callout titles (#1207))
{props.type || "Note"}
}