You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: rfcs/2026-async-react.md
+45Lines changed: 45 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -207,6 +207,51 @@ function App() {
207
207
}
208
208
```
209
209
210
+
#### Form errors
211
+
212
+
When an error is thrown in a form's `submitAction`, it will be available via the `actionError` render prop. This can be displayed to the user by rendering an `<Alert>`, which will be focused and announced by screen readers. For field-level errors (e.g. server validation), a special error object compatible with [Standard Schema](https://standardschema.dev/schema) could be supported, allowing these errors to be automatically propagated to the correct fields (as we support via the `validationErrors` prop today).
213
+
214
+
**Note**: This proposes a separate `submitAction` prop rather than overloading the existing `action` prop supported by React. `submitAction` has a few differences from `action`:
215
+
216
+
* Errors thrown during the action are caught and passed to the `actionError` render prop.
217
+
* The pending state is automatically passed to the form's submit button. Alternatively we could use React's [useFormStatus](https://react.dev/reference/react-dom/hooks/useFormStatus) hook for that, but this has [bugs](https://github.com/facebook/react/issues/30368) at the moment.
218
+
* The form is not automatically reset after the action completes. This is a [controversial](https://github.com/facebook/react/issues/29034) behavior that is often unwanted (e.g. when errors occur). If a reset is desired, it can be triggered manually via `ReactDOM.requestFormReset`.
219
+
220
+
```tsx
221
+
function App() {
222
+
return (
223
+
<Form
224
+
submitAction={async (formData) => {
225
+
let email =formData.get('email');
226
+
if (!awaitisAccountAvailable(email)) {
227
+
throw {
228
+
issues: [{
229
+
message: 'An account with that email already exists',
230
+
path: ['email']
231
+
}]
232
+
}
233
+
}
234
+
235
+
try {
236
+
awaitcreateAccount(email);
237
+
} catch {
238
+
throw'Could not create account';
239
+
}
240
+
}}>
241
+
{({actionError}) => (
242
+
<>
243
+
{actionError&&
244
+
<Alert>{String(actionError)}</Alert>
245
+
}
246
+
<TextFieldname="email" />
247
+
<Buttontype="submit">Submit</Button>
248
+
</>
249
+
)}
250
+
</Form>
251
+
);
252
+
}
253
+
```
254
+
210
255
## Documentation
211
256
212
257
We'll add new examples to our documentation showing how to use action props, and add pending states to components in our starter kits.
0 commit comments