useActionState は、フォームアクションの結果に基づいて状態を更新できる Hook です。

const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);

注記

以前の React Canary バージョンでは、この API は React DOM の一部であり、useFormState と呼ばれていました。


リファレンス

useActionState(action, initialState, permalink?)

コンポーネントのトップレベルで useActionState を呼び出して、フォームアクションが呼び出されたときに更新されるコンポーネント状態を作成します。useActionState に既存のフォームアクション関数と初期状態を渡すと、フォームで使用する新しいアクションと最新のフォーム状態、およびアクションがまだ保留中かどうかが返されます。最新のフォーム状態は、指定した関数にも渡されます。

import { useActionState } from "react";

async function increment(previousState, formData) {
return previousState + 1;
}

function StatefulForm({}) {
const [state, formAction] = useActionState(increment, 0);
return (
<form>
{state}
<button formAction={formAction}>Increment</button>
</form>
)
}

フォームの状態は、フォームが最後に送信されたときにアクションによって返された値です。フォームがまだ送信されていない場合は、渡した初期状態です。

サーバー関数で使用する場合、useActionState を使用すると、ハイドレーションが完了する前に、フォームの送信に対するサーバーの応答を表示できます。

以下の例をご覧ください。

パラメータ

  • fn: フォームが送信されたとき、またはボタンが押されたときに呼び出される関数。関数が呼び出されると、フォームの以前の状態(最初は渡したinitialState、その後は以前の戻り値)が最初の引数として渡され、その後にフォームアクションが通常受信する引数が続きます。
  • initialState: 状態を最初に設定する値。シリアライズ可能な値を指定できます。この引数は、アクションが最初に呼び出された後は無視されます。
  • オプション permalink: このフォームが変更する一意のページ URL を含む文字列。プログレッシブエンハンスメントと組み合わせて、動的コンテンツ(例:フィード)のあるページで使用します。fnサーバー関数で、JavaScript バンドルがロードされる前にフォームが送信された場合、ブラウザは現在のページの URL ではなく、指定されたパーマリンク URL に移動します。React が状態を渡し方を知るように、宛先ページに同じフォームコンポーネントがレンダリングされるようにしてください(同じアクションfnpermalink を含む)。フォームがハイドレートされると、このパラメータは効果がありません。

戻り値

useActionState は、次の値を持つ配列を返します。

  1. 現在の状態。最初のレンダリング中は、渡した initialState と一致します。アクションが呼び出された後は、アクションによって返された値と一致します。
  2. form コンポーネントの action プロパティ、またはフォーム内の任意の button コンポーネントの formAction プロパティとして渡すことができる新しいアクション。
  3. 保留中のトランジションがあるかどうかを示す isPending フラグ。

注意事項

  • React Server Componentsをサポートするフレームワークと併用する場合、`useActionState`を使用すると、クライアント側でJavaScriptが実行される前にフォームをインタラクティブにすることができます。Server Componentsを使用しない場合、これはコンポーネントのローカル状態と同等です。
  • `useActionState`に渡される関数は、追加の引数として、以前または初期の状態を最初の引数として受け取ります。そのため、`useActionState`を使用せずにフォームアクションとして直接使用した場合とは、シグネチャが異なります。

使用方法 {/* svg省略 */}

フォームアクションから返された情報の使用 {/* svg省略 */}

アクションの戻り値にアクセスするには、コンポーネントのトップレベルで`useActionState`を呼び出します。この戻り値は、フォームが最後に送信されたときのアクションの戻り値です。

import { useActionState } from 'react';
import { action } from './actions.js';

function MyComponent() {
const [state, formAction] = useActionState(action, null);
// ...
return (
<form action={formAction}>
{/* ... */}
</form>
);
}

`useActionState`は、以下の項目を含む配列を返します。

  1. フォームの現在の状態。これは、最初に指定した初期状態に設定され、フォームが送信された後は、指定したアクションの戻り値に設定されます。
  2. `<form>`の`action` propとして渡す新しいアクション
  3. アクションの処理中に利用できる保留状態

フォームが送信されると、指定したアクション関数が呼び出されます。その戻り値は、フォームの新しい現在の状態になります。

指定するアクションは、新しい最初の引数、つまりフォームの現在の状態も受け取ります。フォームが最初に送信されたとき、これは指定した初期状態になりますが、後続の送信では、アクションが最後に呼び出されたときの戻り値になります。残りの引数は、`useActionState`が使用されていない場合と同じです。

function action(currentState, formData) {
// ...
return 'next state';
}

フォーム送信後に情報を表示する {/* svg省略 */}

1〜の 2:
フォームエラーの表示 {/* svg省略 */}

サーバー関数から返されたエラーメッセージやトーストなどのメッセージを表示するには、`useActionState`の呼び出しでアクションをラップします。

import { useActionState, useState } from "react";
import { addToCart } from "./actions.js";

function AddToCartForm({itemID, itemTitle}) {
  const [message, formAction, isPending] = useActionState(addToCart, null);
  return (
    <form action={formAction}>
      <h2>{itemTitle}</h2>
      <input type="hidden" name="itemID" value={itemID} />
      <button type="submit">Add to Cart</button>
      {isPending ? "Loading..." : message}
    </form>
  );
}

export default function App() {
  return (
    <>
      <AddToCartForm itemID="1" itemTitle="JavaScript: The Definitive Guide" />
      <AddToCartForm itemID="2" itemTitle="JavaScript: The Good Parts" />
    </>
  )
}

トラブルシューティング {/* svg省略 */}

アクションが送信されたフォームデータを読み取れなくなりました {/* svg省略 */}

アクションを`useActionState`でラップすると、*最初の引数として*追加の引数が渡されます。そのため、送信されたフォームデータは、通常は最初の引数ですが、*2番目の*引数になります。新たに追加される最初の引数は、フォームの現在の状態です。

function action(currentState, formData) {
// ...
}