-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(en): merge reactjs.org/main into zh-hans.reactjs.org/main @ 10574e5
(#1345)
- Loading branch information
Showing
3 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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` package. | ||
|
||
</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 to the UI based on the status of the 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> | ||
); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
--- | ||
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 gives you status information of the last form submission. | ||
|
||
```js | ||
const { pending, data, method, action } = useFormStatus(); | ||
``` | ||
|
||
</Intro> | ||
|
||
<InlineToc /> | ||
|
||
--- | ||
|
||
## Reference {/*reference*/} | ||
|
||
### `useFormStatus()` {/*use-form-status*/} | ||
|
||
The `useFormStatus` Hook provides status information of the last form submission. | ||
|
||
```js {5},[[1, 6, "status.pending"]] | ||
import { useFormStatus } from "react-dom"; | ||
import action from './actions'; | ||
|
||
function Submit() { | ||
const status = useFormStatus(); | ||
return <button disabled={status.pending}>Submit</button> | ||
} | ||
|
||
export default App() { | ||
return ( | ||
<form action={action}> | ||
<Submit /> | ||
</form> | ||
); | ||
} | ||
``` | ||
|
||
To get status information, the `Submit` component must be rendered within a `<form>`. The Hook returns information like the <CodeStep step={1}>`pending`</CodeStep> property which tells you if the form is actively submitting. | ||
|
||
In the above example, `Submit` uses this information to disable `<button>` presses while the form is submitting. | ||
|
||
[See more examples below.](#usage) | ||
|
||
#### Parameters {/*parameters*/} | ||
|
||
`useFormStatus` does not take any parameters. | ||
|
||
#### Returns {/*returns*/} | ||
|
||
A `status` object with the following properties: | ||
|
||
* `pending`: A boolean. If `true`, this means the parent `<form>` is pending submission. Otherwise, `false`. | ||
|
||
* `data`: An object implementing the [`FormData interface`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) that contains the data the parent `<form>` is submitting. If there is no active submission or no parent `<form>`, it will be `null`. | ||
|
||
* `method`: A string value of either `'get'` or `'post'`. This represents whether the parent `<form>` is submitting with either a `GET` or `POST` [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods). By default, a `<form>` will use the `GET` method and can be specified by the [`method`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#method) property. | ||
|
||
[//]: # (Link to `<form>` documentation. "Read more on the `action` prop on `<form>`.") | ||
* `action`: A reference to the function passed to the `action` prop on the parent `<form>`. If there is no parent `<form>`, the property is `null`. If there is a URI value provided to the `action` prop, or no `action` prop specified, `status.action` will be `null`. | ||
|
||
#### Caveats {/*caveats*/} | ||
|
||
* The `useFormStatus` Hook must be called from a component that is rendered inside a `<form>`. | ||
* `useFormStatus` will only return status information for a parent `<form>`. It will not return status information for any `<form>` rendered in that same component or children components. | ||
|
||
--- | ||
|
||
## 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, you can call the `useFormStatus` Hook in a component rendered in a `<form>` and read the `pending` property returned. | ||
|
||
Here, we use the `pending` property to indicate the form is submitting. | ||
|
||
<Sandpack> | ||
|
||
```js App.js | ||
import { useFormStatus } from "react-dom"; | ||
import { submitForm } from "./actions.js"; | ||
|
||
function Submit() { | ||
const { pending } = useFormStatus(); | ||
return ( | ||
<button type="submit" disabled={pending}> | ||
{pending ? "Submitting..." : "Submit"} | ||
</button> | ||
); | ||
} | ||
|
||
function Form({ action }) { | ||
return ( | ||
<form action={action}> | ||
<Submit /> | ||
</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": "canary", | ||
"react-dom": "canary", | ||
"react-scripts": "^5.0.0" | ||
}, | ||
"main": "/index.js", | ||
"devDependencies": {} | ||
} | ||
``` | ||
</Sandpack> | ||
|
||
<Pitfall> | ||
|
||
##### `useFormStatus` will not return status information for a `<form>` rendered in the same component. {/*useformstatus-will-not-return-status-information-for-a-form-rendered-in-the-same-component*/} | ||
|
||
The `useFormStatus` Hook only returns status information for a parent `<form>` and not for any `<form>` rendered in the same component calling the Hook, or child components. | ||
|
||
```js | ||
function Form() { | ||
// 🚩 `pending` will never be true | ||
// useFormStatus does not track the form rendered in this component | ||
const { pending } = useFormStatus(); | ||
return <form action={submit}></form>; | ||
} | ||
``` | ||
|
||
Instead call `useFormStatus` from inside a component that is located inside `<form>`. | ||
|
||
```js | ||
function Submit() { | ||
// ✅ `pending` will be derived from the form that wraps the Submit component | ||
const { pending } = useFormStatus(); | ||
return <button disabled={pending}>...</button>; | ||
} | ||
|
||
function Form() { | ||
// This is the <form> `useFormStatus` tracks | ||
return ( | ||
<form action={submit}> | ||
<Submit /> | ||
</form> | ||
); | ||
} | ||
``` | ||
|
||
</Pitfall> | ||
|
||
### Read the form data being submitted {/*read-form-data-being-submitted*/} | ||
|
||
You can use the `data` property of the status information returned from `useFormStatus` to display what data is being submitted by the user. | ||
|
||
Here, we have a form where users can request a username. We can use `useFormStatus` to display a temporary status message confirming what username they have requested. | ||
|
||
<Sandpack> | ||
|
||
```js UsernameForm.js active | ||
import {useState, useMemo, useRef} from 'react'; | ||
import {useFormStatus} from 'react-dom'; | ||
|
||
export default function UsernameForm() { | ||
const {pending, data} = useFormStatus(); | ||
|
||
const [showSubmitted, setShowSubmitted] = useState(false); | ||
const submittedUsername = useRef(null); | ||
const timeoutId = useRef(null); | ||
|
||
useMemo(() => { | ||
if (pending) { | ||
submittedUsername.current = data?.get('username'); | ||
if (timeoutId.current != null) { | ||
clearTimeout(timeoutId.current); | ||
} | ||
|
||
timeoutId.current = setTimeout(() => { | ||
timeoutId.current = null; | ||
setShowSubmitted(false); | ||
}, 2000); | ||
setShowSubmitted(true); | ||
} | ||
}, [pending, data]); | ||
|
||
return ( | ||
<> | ||
<label>Request a Username: </label><br /> | ||
<input type="text" name="username" /> | ||
<button type="submit" disabled={pending}> | ||
{pending ? 'Submitting...' : 'Submit'} | ||
</button> | ||
{showSubmitted ? ( | ||
<p>Submitted request for username: {submittedUsername.current}</p> | ||
) : null} | ||
</> | ||
); | ||
} | ||
``` | ||
```js App.js | ||
import UsernameForm from './UsernameForm'; | ||
import { submitForm } from "./actions.js"; | ||
|
||
export default function App() { | ||
return ( | ||
<form action={submitForm}> | ||
<UsernameForm /> | ||
</form> | ||
); | ||
} | ||
``` | ||
```js actions.js hidden | ||
export async function submitForm(query) { | ||
await new Promise((res) => setTimeout(res, 1000)); | ||
} | ||
``` | ||
```json package.json hidden | ||
{ | ||
"dependencies": { | ||
"react": "canary", | ||
"react-dom": "canary", | ||
"react-scripts": "^5.0.0" | ||
}, | ||
"main": "/index.js", | ||
"devDependencies": {} | ||
} | ||
``` | ||
</Sandpack> | ||
--- | ||
## Troubleshooting {/*troubleshooting*/} | ||
### `status.pending` is never `true` {/*pending-is-never-true*/} | ||
`useFormStatus` will only return status information for a parent `<form>`. | ||
If the component that calls `useFormStatus` is not nested in a `<form>`, `status.pending` will always return `false`. Verify `useFormStatus` is called in a component that is a child of a `<form>` element. | ||
`useFormStatus` will not track the status of a `<form>` rendered in the same component. See [Pitfall](#useformstatus-will-not-return-status-information-for-a-form-rendered-in-the-same-component) for more details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -161,6 +161,17 @@ | |
"hasSectionHeader": true, | ||
"sectionHeader": "[email protected]" | ||
}, | ||
{ | ||
"title": "Hook", | ||
"path": "/reference/react-dom/hooks", | ||
"routes": [ | ||
{ | ||
"title": "useFormStatus", | ||
"path": "/reference/react-dom/hooks/useFormStatus", | ||
"canary": true | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "组件", | ||
"path": "/reference/react-dom/components", | ||
|