🐬

useFormStateのStateをリセットする

2024/08/26に公開

ReactのuseFormState(useActionState)を使用している人向けの記事になります。

useFormStateについて

新規にリリースされるReactではuseActionStateに名前が変更されておりますが、現在の安定版ではuseFormStateになっています。
React標準のHooksですが現時点ではNext.jsのServer Actionsで使用する機会が多いと思います。(筆者もApp Routerで使用しています)

機能としては命名通りフォームの状態をサーバーと共有するためのHooksです。

使い方

定義は以下となっており、第一引数にFormAction、第二引数にStateを設定します。permalink?は今回の説明とあまり関係ないので割愛します。
useFormState(action, initialState, permalink?)

問題

今回重要なのはこの第二引数のStateでした。
Server Actionsでサーバー側の処理が成功後にStateが成功状態になります。そのためフォーム送信成功後に画面遷移が走らないと、フォームの状態がいつまで残ってしまいます。
例えば今回問題となったのはダイヤログにForm機能があり、送信後にもダイヤログに送信成功後の状態が残ってしまうため、再度ダイヤログを表示すると成功状態が表示されてしまいました。

解決方法

useFormStateのState状態をリセットして上げればいいのですが、探してみましがとくにリセットするAPIが提供はされておりませんでした。
そのため解決方法としてコンポーネント自体を再マウントすることで初期化させることにします。

やり方としてはダイヤログが閉じたタイミングでcallbackを呼び出して、keyの値を更新するようにしました。

// UUIDを指定していますが、他の値であれば何でも大丈夫です
const [uuid, setUUID] = useState(crypto.randomUUID())

return (
    <section className={`flex justify-end`}>
      <Dialog
        key={uuid}
        initFormState={{ success: false }}
        closeDialog={() => {
          // ダイヤログを閉じた時にUUIDを変更することで、ダイヤログの状態をリセットする
          setUUID(crypto.randomUUID())
        }}
      />
    </section>
  )

補足

基本的にReactでは毎回再マウントさせるのはアンチパターンなので基本的には再描画させてください。ただし今回のようにuseFormStateの状態をリセットさせるやり方が思いつかなかったので、再マウントさせるやり方をしました。

Discussion