useFormStatus - This feature is available in the latest Canary

useFormStatus は、直近のフォーム送信に関するステータス情報を提供するフックです。

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

リファレンス

useFormStatus()

useFormStatus フックは、直近のフォーム送信に関するステータス情報を提供します。

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

ステータス情報を取得するには、この Submit コンポーネントが <form> 内でレンダーされている必要があります。このフックは、フォームが送信中かどうかを示す pending プロパティなどの情報を返します。

上記の例では、Submit がこの情報を使用して、フォームが送信中の間 <button> を無効にして押せなくしています。

さらに例を見る

引数

useFormStatus は引数を受け取りません。

返り値

以下のプロパティを持つ status オブジェクト。

  • pending: ブーリアン。true の場合、親 <form> で送信が進行中であることを意味します。それ以外の場合は false となります。

  • data: FormData インターフェースを実装したオブジェクト。親 <form> が送信中のデータを含んでいます。送信がアクティブでない場合や親 <form> がない場合は null になります。

  • method: 'get' または 'post' のいずれかの文字列。親 <form>GETPOST HTTP メソッドのどちらで送信されているかを表します。デフォルトでは、<form>GET メソッドを使用しますが、method によって指定することができます。

  • action: 親 <form> の props である action に渡された関数への参照。親 <form> がない場合、このプロパティは null です。action プロパティに URI 値が渡された場合や action プロパティが指定されていない場合も、status.actionnull になります。

注意点

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

こうするのではなく、useFormStatus<form> の内部にあるコンポーネントから呼び出してください。

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.pendingtrue にならない

useFormStatus は親の <form> に対するステータス情報のみを返します。

useFormStatus を呼び出しているコンポーネントが <form> の中にネストされていない場合、status.pending は常に false を返します。useFormStatus<form> 要素の子コンポーネント内で呼び出されていることを確認してください。

useFormStatus は、同じコンポーネントでレンダーされた <form> の状態は追跡しません。詳細は落とし穴欄を参照してください。