From f2293e5ed2222fe43339e61966ae190c4157f781 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 01/32] Fix useSubmission --- .../reference/data-apis/use-submission.mdx | 216 +++++------------- 1 file changed, 61 insertions(+), 155 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 1ba58fa79..b4e9f969d 100644 --- a/src/routes/solid-router/reference/data-apis/use-submission.mdx +++ b/src/routes/solid-router/reference/data-apis/use-submission.mdx @@ -1,175 +1,81 @@ --- title: useSubmission -use_cases: >- - form feedback, pending states, optimistic updates, error handling, single - submission tracking -tags: - - forms - - submissions - - pending - - optimistic - - errors - - feedback -version: '1.0' -description: >- - Track form submission states with useSubmission. Handle pending feedback, - optimistic updates, and errors for single forms. --- -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 data 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 ( - <> -Latest valid submittion: {latestValidSubmission.result}
; } ``` -## 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.message}
- - -Latest valid submittion: {latestValidSubmission.result}
; + returnLatest valid submission: {latestValidSubmission.result}
; } ``` ## 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 f03cb70b4..51e09dbaa 100644 --- a/src/routes/solid-router/reference/data-apis/use-submissions.mdx +++ b/src/routes/solid-router/reference/data-apis/use-submissions.mdx @@ -16,189 +16,111 @@ description: >- history, handle errors, and show optimistic updates. --- -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 ( +Failed submissions:
+Error: {error().message}
+ + +{result().message}
+ )} +Error: {submission.result.message}
+ + + + } + > +Settings saved successfully!
+{error().message}
+ +{error()}
}{post.title}
}Error: {error().message}
- - -Failed to add post. Please try again.
{result().message}
- )} -Error: {submission.result.message}
- - - - } - > -Settings saved successfully!
+Error: {submission.result.message}
{error().message}
- -{errors().server}
{error()}
}{errors().title}
+Failed to add post. Please try again.
-{errors().server}
-{errors().title}
+ +{errors().code}
{post.title}
}{device.name}
}{post.title}
}{item.name}
}{article.title}
}Items: {items()?.length}
++ {stat.label}: {stat.value} +
+ )} +{error().message}
- - -{submission.result.message}
+ + +Latest valid submission: {latestValidSubmission.result}
; } ``` - -## Parameters - -- **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. - 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. 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 8777bdb73..3f6a249da 100644 --- a/src/routes/solid-router/reference/data-apis/use-submissions.mdx +++ b/src/routes/solid-router/reference/data-apis/use-submissions.mdx @@ -16,22 +16,50 @@ description: >- history, handle errors, and show optimistic updates. --- -The `useSubmissions` function retrieves the state of all submissions for a given action. +The `useSubmissions` primitive returns the state of all submissions for a given action. + +## Parameters + +- `action`: + The action to track. +- `filter` (optional): + A function that filters submissions. + It is executed for each submission in the order of creation. + It receives an array of the action's inputs as a parameter and must return `true` to select the submission or `false` otherwise. + +## Returns + +`useSubmissions` returns a reactive array of submission objects. +Each submission object has the following properties: + +- `input`: + The reactive input data of the action. +- `result`: + A reactive value representing the successful return value of the action. +- `error`: + A reactive value for any error thrown by the action. +- `pending`: + A reactive boolean indicating if the action is currently running. +- `clear`: + A function to clear the submission's state. +- `retry`: + A function to re-execute the submission with the same input. + +## Examples + +### Basic usage ```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; -}, "add-todo"); - -export default function AddTodoForm() { + // ... Sends the todo data to the server. +}, "addTodo"); + +function AddTodoForm() { const submissions = useSubmissions(addTodoAction); + return (Failed submissions:
@@ -101,26 +122,3 @@ function FailedTodos() { ); } ``` - -## Parameters - -- **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. - -## Returns - -`useSubmissions` returns an array of submissions. -Each submission is an object containing the following properties: - -- **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 1916db028ade9af44485471a8a72adc085cf5954 Mon Sep 17 00:00:00 2001 From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com> Date: Sat, 16 Aug 2025 07:20:27 +0330 Subject: [PATCH 10/32] update --- .../solid-router/reference/data-apis/action.mdx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/routes/solid-router/reference/data-apis/action.mdx b/src/routes/solid-router/reference/data-apis/action.mdx index e89dff060..382f0721c 100644 --- a/src/routes/solid-router/reference/data-apis/action.mdx +++ b/src/routes/solid-router/reference/data-apis/action.mdx @@ -9,13 +9,15 @@ This state can be accessed with the [`useSubmission`](/solid-router/reference/da ## Parameters -- `handler`: - An asynchronous function that performs the action's logic. - When the action is used with a [`{errors().code}
Items: {items()?.length}
+{user()}
-{user()?.name}
; +} ``` -## Options +### Handling loading and errors + +```tsx +import { Suspense, ErrorBoundary, For } from "solid-js"; +import { createAsync, query } from "@solidjs/router"; + +const getUserQuery = query(async (id: string) => { + // ... Fetches the user from the server. +}, "user"); -| Name | Type | Default | Description | -| ------------ | ----------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| name | `string` | `undefined` | A name for the resource. This is used for debugging purposes. | -| deferStream | `boolean` | `false` | If true, Solid will wait for the resource to resolve before flushing the stream. | -| initialValue | `any` | `undefined` | The initial value of the resource. | -| onHydrated | `function` | `undefined` | A callback that is called when the resource is hydrated. | -| ssrLoadFrom | `"server" \| "initial"` | `"server"` | The source of the initial value for SSR. If set to `"initial"`, the resource will use the `initialValue` option instead of the value returned by the fetcher. | -| storage | `function` | `createSignal` | A function that returns a signal. This can be used to create a custom storage for the resource. This is still experimental +function UserProfile() { + const user = createAsync(() => getUserQuery()); + + return ( +{user()!.name}
+Current name: {props.data.product?.name}
+{article.title}
}- {stat.label}: {stat.value} -
- )} -{article.title}
}+ {stat.label}: {stat.value} +
+ )} +Count: {count()}
-Count: {count()}
-