Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add useFormStatus Hook API reference documentation #6314

Merged
merged 4 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/content/reference/react-dom/hooks/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: "React DOM Hooks"
---

<Intro>

The `react-dom` package contains Hooks that are only supported for web applications (which run in the browser DOM environment). These Hooks are not supported in non-browser environments like iOS, Android, or Windows applications. If you are looking for Hooks that are supported in web browsers *and other environments* see [the React Hooks page](/reference/react). This page lists all the Hooks in the `react-dom` packakge.

</Intro>

---

## Form Hooks {/*form-hooks*/}

<Canary>

Form Hooks are currently only available in React's canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).

</Canary>

*Forms* let you create interactive controls for submitting information. To manage forms in your components, use one of these Hooks:

* [`useFormStatus`](/reference/react-dom/hooks/useFormStatus) allows you to make updates the UI based on the status of a form.
* `useFormState` allows you to manage state inside a form.

```js
function Form({ action }) {
async function increment(n) {
return n + 1;
}
const [count, incrementFormAction] = useFormState(increment, 0);
return (
<form action={action}>
<button formAction={incrementFormAction}>Count: {count}</button>
<Button />
</form>
);
}

function Button() {
const { pending } = useFormStatus();
return (
<button disabled={pending} type="submit">
Submit
</button>
);
}
```
166 changes: 166 additions & 0 deletions src/content/reference/react-dom/hooks/useFormStatus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: useFormStatus
canary: true
---

<Canary>

The `useFormStatus` Hook is currently only available in React's canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).

</Canary>

<Intro>

`useFormStatus` is a Hook that allows you to make updates to the UI based on the status of a form.

```js
const { pending } = useFormStatus();
```

</Intro>

<InlineToc />

---

## Reference {/*reference*/}

### `useFormStatus()` {/*usformstatus*/}


Call `useFormStatus` at the top level of your component to subscribe to the status of the form that wraps your component.

```js
function Button() {
const { pending } = useFormStatus();
return <button disabled={pending}>Submit</button>
}
```

The `useFormStatus` Hook provides information on the form's status, like when the form is pending. The `pending` property indicates whether the form is currently in the process of being submitted. You can use this property to update the UI while the form is being submitted like disabling form submission buttons or the wording in your UI.

[See more examples below.](#usage)

#### Parameters {/*parameters*/}

`useFormStatus` does not take any parameters.

#### Returns {/*returns*/}

* `pending`: A boolean. If true, the form wrapping the Component calling `useFormStatus` is pending submission.

#### Caveats {/*caveats*/}

* The `useFormStatus` Hook must be called from a Component that is located inside `<form>`. You cannot call `useFormStatus` from the same Component that returns `<form>`.

---

## Usage {/*usage*/}

### Display a pending state during form submission {/*display-a-pending-state-during-form-submission*/}
To display a pending state while a form is submitting, call the `useFormStatus` Hook at the top level of a component that is wraped in the form. The `useFormStatus` Hook provides the `pending` property which is `true` when the form is in the process of being submitted and `false` otherwise. You can use this property to disable the submit button when a form is already being submitted. You can also change the text of the UI to indicate the form is submitting, like changing the text of a button from "Submit" to "Submitting".

<Sandpack>

```js App.js
import { experimental_useFormStatus as useFormStatus } from "react-dom";
import { submitForm } from "./actions.js";

function Button() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Submitting..." : "Submit"}
</button>
);
}

function Form({ action }) {
return (
<form action={action}>
<Button />
</form>
);
}

export default function App() {
return <Form action={submitForm} />;
}
```

```js actions.js hidden
export async function submitForm(query) {
await new Promise((res) => setTimeout(res, 1000));
}
```

```json package.json hidden
{
"dependencies": {
"react": "experimental",
"react-dom": "experimental",
"react-scripts": "^5.0.0"
},
"main": "/index.js",
"devDependencies": {}
}
```
</Sandpack>

<Pitfall>

The `useFormStatus` Hook must be called from a Component that is located inside `<form>`. You cannot call `useFormStatus` from the same Component that returns `<form>`.

```js
function Form() {
const { pending } = useFormStatus() // 🚩 `pending` will never be `true`
return <form action={submit}></form>
}
```

Instead call `useFormStatus` from inside a Component that is located inside `<form>`.

```js
function Button(){
lunaleaps marked this conversation as resolved.
Show resolved Hide resolved
// ✅ `pending` will be derived from the
// form that wraps the Button Component
const { pending } = useFormStatus()
return <button disabled={pending}> //...
}

function Form() {
return <form><Button /></form>
}
```

</Pitfall>

---

## Troubleshooting {/*troubleshooting*/}

### `pending` is never `true` {/*pending-is-never-true*/}

The `pending` attribute will always have the value `true` if the `useFormStatus` Hook is called from the same component that returns `<form>`. The `useFormStatus` Hook must be called from a Component that is located inside `<form>`. You cannot call `useFormStatus` from the same Component that returns `<form>`.

```js
function Form() {
const { pending } = useFormStatus() // 🚩 `pending` will never be `true`
return <form action={submit}> //...
}
```

Instead call `useFormStatus` from inside a Component that is located inside `<form>`.

```js
function Button(){
// ✅ `pending` will be derived from the
// form that wraps the Button Component
const { pending } = useFormStatus()
return <button disabled={pending}> //...
}

function Form() {
return <form><Button /></form>
}
```
11 changes: 11 additions & 0 deletions src/sidebarReference.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@
"hasSectionHeader": true,
"sectionHeader": "[email protected]"
},
{
"title": "Hooks",
"path": "/reference/react-dom/hooks",
"routes": [
{
"title": "useFormStatus",
"path": "/reference/react-dom/hooks/useFormStatus",
"canary": true
}
]
},
{
"title": "Components",
"path": "/reference/react-dom/components",
Expand Down
Loading