|
| 1 | +--- |
| 2 | +title: useSubmissions |
| 3 | +--- |
| 4 | + |
| 5 | +This helper is used to handle form submissions and can provide optimistic updates while actions are in flight as well as pending state feedback. |
| 6 | +This method will return an iterable of all submitted actions while its component is mounted. With an optional second parameter for a filter function. |
| 7 | + |
| 8 | +<Callout type="tip"> |
| 9 | +If you only care for the latest submission, you can use the [`useSubmission`](/solid-router/reference/data-apis/use-submission) helper. |
| 10 | + </Callout> |
| 11 | + |
| 12 | +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. |
| 13 | + |
| 14 | +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. |
| 15 | + |
| 16 | +```tsx title="component.tsx" {4,9-20, 23} |
| 17 | +import { useSubmissions } from "@solidjs/router"; |
| 18 | + |
| 19 | +function Component() { |
| 20 | + const submissions = useSubmissions(postNameAction); |
| 21 | + |
| 22 | + return ( |
| 23 | + <form method="post" action={postNameAction}> |
| 24 | + <ul> |
| 25 | + <For each={Array.from(submissions.entries())}> |
| 26 | + {([attemptIndex, data]) => ( |
| 27 | + <Show when={data.result}> |
| 28 | + { result => ( |
| 29 | + <li> |
| 30 | + Backend {attemptIndex}: {result.name} |
| 31 | + </li> |
| 32 | + )} |
| 33 | + </Show> |
| 34 | + </> |
| 35 | + )} |
| 36 | + </For> |
| 37 | + </ul> |
| 38 | + <input name="name" type="text" /> |
| 39 | + <button type="submit">{submissions.pending ? "sending" : "send"}</button> |
| 40 | + </form> |
| 41 | + ) |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +## Creating the action |
| 46 | + |
| 47 | +The Action which will trigger the submission should be created with the [`action()`](/solid-router/reference/data-apis/action) helper and, when in a [SolidStart](/solid-start) app. If in a [SolidStart](/solid-start) app to leverage the caching and RPC capabilities from the server-side. |
| 48 | + |
| 49 | +```tsx title="/component.tsx" {1,3-4} |
| 50 | +import { action } from "@solidjs/router"; |
| 51 | + |
| 52 | +const postNameAction = action(() => { |
| 53 | + "use server"; |
| 54 | + /*... logic ...*/ |
| 55 | + return { data: "Hello SolidStart" }; |
| 56 | +}) |
| 57 | + |
| 58 | +``` |
| 59 | + |
| 60 | +## Filtering Submissions |
| 61 | + |
| 62 | +As an optional second parameter, the `useSubmissions` helper can receive a filter function to only return the submission that matches the condition. |
| 63 | +The filter receives the submitted dated as a parameter and should return a boolean value. |
| 64 | +E.g.: action below will only submit if the name is "solid". |
| 65 | + |
| 66 | +```tsx title="component.tsx" {4-8} |
| 67 | +import { useSubmissions } from "@solidjs/router"; |
| 68 | + |
| 69 | +function Component() { |
| 70 | + const submissions = useSubmissions(postNameAction, ([formData]) => { |
| 71 | + const name = formData.get("name") ?? ""; |
| 72 | + |
| 73 | + return name === "solid"; |
| 74 | + }); |
| 75 | + |
| 76 | + return ( |
| 77 | + <form method="post" action={postNameAction}> |
| 78 | + <ul> |
| 79 | + <For each={Array.from(submissions.entries())}> |
| 80 | + {([attemptIndex, data]) => ( |
| 81 | + <Show when={data.result}> |
| 82 | + { result => ( |
| 83 | + <li> |
| 84 | + Backend {attemptIndex}: {result.name} |
| 85 | + </li> |
| 86 | + )} |
| 87 | + </Show> |
| 88 | + </> |
| 89 | + )} |
| 90 | + </For> |
| 91 | + </ul> |
| 92 | + <input name="name" type="text" /> |
| 93 | + <button type="submit">{submissions.pending ? "sending" : "send"}</button> |
| 94 | + </form> |
| 95 | + ) |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +## Optimistic Updates |
| 100 | + |
| 101 | +When the form is submitted, the `submission` object will be updated with the new value and the `pending` property will be set to `true`. |
| 102 | +This allows you to provide feedback to the user that the action is in progress. |
| 103 | +Once the action is complete, the `pending` property will be set to `false` and the `result` property will be updated with final value. |
| 104 | + |
| 105 | + |
| 106 | +<TabsCodeBlocks> |
| 107 | +<div id="ts"> |
| 108 | +```tsx title="component.tsx" {5,12-19} |
| 109 | +import { Show } from "solid-js"; |
| 110 | +import { useSubmissions } from "@solidjs/router"; |
| 111 | + |
| 112 | +function Component() { |
| 113 | + const submissions = useSubmissions(postNameAction); |
| 114 | + |
| 115 | + return ( |
| 116 | + <form method="post" action={postNameAction}> |
| 117 | + <ul> |
| 118 | + <For each={Array.from(submissions.entries())}> |
| 119 | + {([attemptIndex, data]) => ( |
| 120 | + <Show when={data.input[0].entries().next()}> |
| 121 | + {(input) => { |
| 122 | + const name = (input().value as [string, string])[1] |
| 123 | + |
| 124 | + return ( |
| 125 | + <li>Optimistic: {name}</li> |
| 126 | + )}} |
| 127 | + </Show> |
| 128 | + )} |
| 129 | + </For> |
| 130 | + </ul> |
| 131 | + <input name="name" type="text" /> |
| 132 | + <button type="submit">{submissions.pending ? "sending" : "send"}</button> |
| 133 | + </form> |
| 134 | + ) |
| 135 | +} |
| 136 | +``` |
| 137 | +</div> |
| 138 | +<div id="js"> |
| 139 | +```tsx title="component.jsx" {5,12-19} |
| 140 | +import { Show } from "solid-js"; |
| 141 | +import { useSubmissions } from "@solidjs/router"; |
| 142 | + |
| 143 | +function Component() { |
| 144 | + const submissions = useSubmissions(postNameAction); |
| 145 | + |
| 146 | + return ( |
| 147 | + <form method="post" action={postNameAction}> |
| 148 | + <ul> |
| 149 | + <For each={Array.from(submissions.entries())}> |
| 150 | + {([attemptIndex, data]) => ( |
| 151 | + <Show when={data.input[0].entries().next()}> |
| 152 | + {(input) => { |
| 153 | + const name = input().value[1] |
| 154 | + |
| 155 | + return ( |
| 156 | + <li>Optimistic: {name}</li> |
| 157 | + )}} |
| 158 | + </Show> |
| 159 | + )} |
| 160 | + </For> |
| 161 | + </ul> |
| 162 | + <input name="name" type="text" /> |
| 163 | + <button type="submit">{submissions.pending ? "sending" : "send"}</button> |
| 164 | + </form> |
| 165 | + ) |
| 166 | +} |
| 167 | +``` |
| 168 | +</div> |
| 169 | +</TabsCodeBlocks> |
| 170 | + |
| 171 | +## Error Handling |
| 172 | + |
| 173 | +If the action fails, the `submission` object will be updated with the error and the `pending` property will be set to `false`. |
| 174 | +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. |
| 175 | + |
| 176 | +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. |
| 177 | + |
| 178 | +```tsx title="component.tsx" {12-18} |
| 179 | +import { Show } from "solid-js"; |
| 180 | +import { useSubmissions } from "@solidjs/router"; |
| 181 | + |
| 182 | +function Component() { |
| 183 | + const submissions = useSubmissions(postNameAction); |
| 184 | + |
| 185 | + return ( |
| 186 | + <form method="post" action={postNameAction}> |
| 187 | + <ul> |
| 188 | + <For each={Array.from(submissions.entries())}> |
| 189 | + {([attempt, data]) => ( |
| 190 | + <Show when={data.error}> |
| 191 | + <li> |
| 192 | + <p>Backend {attempt}: {data.error.message}</p> |
| 193 | + <button onClick={() => data.retry()}>retry</button> |
| 194 | + <button onClick={() => data.clear()}>clear</button> |
| 195 | + </li> |
| 196 | + </Show> |
| 197 | + )} |
| 198 | + </For> |
| 199 | + </ul> |
| 200 | + <input name="name" type="text" required autocomplete="off" /> |
| 201 | + <button type="submit">{submissions.pending ? "sending" : "send"}</button> |
| 202 | + </form> |
| 203 | + ) |
| 204 | +} |
| 205 | +``` |
0 commit comments