useActionState
は、フォームアクションの結果に基づいて状態を更新できる Hook です。
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);
リファレンス
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 が状態を渡し方を知るように、宛先ページに同じフォームコンポーネントがレンダリングされるようにしてください(同じアクションfn
とpermalink
を含む)。フォームがハイドレートされると、このパラメータは効果がありません。
戻り値
useActionState
は、次の値を持つ配列を返します。
- 現在の状態。最初のレンダリング中は、渡した
initialState
と一致します。アクションが呼び出された後は、アクションによって返された値と一致します。 form
コンポーネントのaction
プロパティ、またはフォーム内の任意のbutton
コンポーネントのformAction
プロパティとして渡すことができる新しいアクション。- 保留中のトランジションがあるかどうかを示す
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`は、以下の項目を含む配列を返します。
- フォームの現在の状態。これは、最初に指定した初期状態に設定され、フォームが送信された後は、指定したアクションの戻り値に設定されます。
- `<form>`の`action` propとして渡す新しいアクション。
- アクションの処理中に利用できる保留状態。
フォームが送信されると、指定したアクション関数が呼び出されます。その戻り値は、フォームの新しい現在の状態になります。
指定するアクションは、新しい最初の引数、つまりフォームの現在の状態も受け取ります。フォームが最初に送信されたとき、これは指定した初期状態になりますが、後続の送信では、アクションが最後に呼び出されたときの戻り値になります。残りの引数は、`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) {
// ...
}