useFormStatus - This feature is available in the latest Canary

useFormStatus 是一个 Hook,它提供上次表单提交的状态信息。

const { pending, data, method, action } = useFormStatus();

参考

useFormStatus()

useFormStatus Hook 提供上次表单提交的状态信息。

import { useFormStatus } from "react-dom";
import action from './actions';

function Submit() {
const status = useFormStatus();
return <button disabled={status.pending}>Submit</button>
}

export default function App() {
return (
<form action={action}>
<Submit />
</form>
);
}

要获取状态信息,必须在<form>内渲染Submit组件。该 Hook 返回诸如pending属性之类的信息,该属性告诉您表单是否正在积极提交。

在上面的示例中,Submit使用此信息在表单提交时禁用<button>点击。

请参见下面的更多示例。

参数

useFormStatus 不接受任何参数。

返回

一个具有以下属性的status 对象

  • pending:布尔值。如果为true,则表示父<form>正在等待提交。否则为false

  • data:一个实现了FormData 接口的对象,其中包含父<form>正在提交的数据。如果没有活动的提交或没有父<form>,它将为null

  • method:一个字符串值,可以是'get''post'。这表示父级<form>元素是使用GET还是POST HTTP 方法提交表单。默认情况下,<form> 元素使用 GET 方法,可以通过 method 属性 指定。

  • action:对传递给父级<form>元素action 属性的函数的引用。如果没有父级<form>元素,则该属性为null。如果为action 属性提供了 URI 值,或者没有指定action 属性,则status.action 将为null

注意事项

  • useFormStatus 钩子必须在渲染在<form>元素内部的组件中调用。
  • useFormStatus 仅返回父级<form>元素的状态信息。它不会返回在同一组件或子组件中渲染的任何<form>元素的状态信息。

使用方法

在表单提交期间显示等待状态

要在表单提交期间显示等待状态,可以在渲染在<form>元素内部的组件中调用useFormStatus 钩子,并读取返回的pending 属性。

这里,我们使用pending 属性来指示表单正在提交。

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} />;
}

陷阱

useFormStatus 不会返回在同一组件中渲染的<form>元素的状态信息。

useFormStatus 钩子只返回父级<form>元素的状态信息,而不是调用该钩子的同一组件或子组件中渲染的任何<form>元素的状态信息。

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>;
}

改为在位于<form>元素内部的组件中调用useFormStatus

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>
);
}

读取正在提交的表单数据

可以使用useFormStatus 返回的状态信息中的data 属性来显示用户正在提交的数据。

这里,我们有一个表单,用户可以在其中请求用户名。我们可以使用useFormStatus 来显示一个临时的状态消息,确认他们请求的用户名。

import {useState, useMemo, useRef} from 'react';
import {useFormStatus} from 'react-dom';

export default function UsernameForm() {
  const {pending, data} = useFormStatus();

  return (
    <div>
      <h3>Request a Username: </h3>
      <input type="text" name="username" disabled={pending}/>
      <button type="submit" disabled={pending}>
        Submit
      </button>
      <br />
      <p>{data ? `Requesting ${data?.get("username")}...`: ''}</p>
    </div>
  );
}


故障排除

status.pending 从未为 true

useFormStatus 只会返回父级 <form> 的状态信息。

如果调用 useFormStatus 的组件没有嵌套在 <form> 中,status.pending 将始终返回 false。请验证 useFormStatus 是否在作为 <form> 元素子组件的组件中调用。

useFormStatus 不会跟踪在同一组件中渲染的 <form> 的状态。详情请参见 陷阱