useActionState

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 的字符串。用于具有动态内容(例如:Feed)的页面以及渐进增强:如果fn是一个服务器函数并且在 JavaScript 包加载之前提交了表单,则浏览器将导航到指定的永久链接 URL,而不是当前页面的 URL。确保在目标页面上呈现相同的表单组件(包括相同的操作fnpermalink),以便 React 知道如何传递状态。一旦表单被水合,此参数将不起作用。

返回值

useActionState 返回一个包含以下值的数组

  1. 当前状态。在第一次渲染期间,它将与您传递的initialState匹配。操作被调用后,它将与操作返回的值匹配。
  2. 一个新的操作,您可以将其作为action prop 传递给您的form组件或formAction prop 传递给表单中的任何button组件。
  3. isPending 标志指示是否存在待处理的转换。

注意事项

  • 当与支持 React 服务器组件的框架一起使用时,useActionState 允许您在客户端执行 JavaScript 之前使表单具有交互性。在不使用服务器组件的情况下,它等同于组件局部状态。
  • 传递给useActionState 的函数接收一个额外的参数,即之前的或初始状态,作为其第一个参数。这使其签名与直接用作表单操作(不使用useActionState)的情况不同。

用法

使用表单操作返回的信息

在组件的顶层调用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. 一个新的操作,您将其作为action 属性传递给<form>
  3. 一个待处理状态,您可以在操作处理时使用。

提交表单时,将调用您提供的操作函数。其返回值将成为表单的新当前状态

您提供的操作还将接收一个新的第一个参数,即表单的当前状态。第一次提交表单时,这将是您提供的初始状态,而后续提交时,它将是上次调用操作的返回值。其余参数与未使用useActionState 时相同。

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

提交表单后显示信息

示例 1 2:
显示表单错误

要显示服务器函数返回的错误消息或提示等消息,请将操作包装在对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" />
    </>
  )
}

疑难解答

我的操作无法再读取提交的表单数据

当您使用 useActionState 包装一个 action 时,它会获得一个额外的参数作为其第一个参数。因此,提交的表单数据将成为其第二个参数,而不是通常的第一个参数。新增的第一个参数是表单的当前状态。

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