useActionState
是一个可以根据某个表单动作的结果更新 state 的 Hook。
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);
参考
useActionState(action, initialState, permalink?)
在组件的顶层调用 useActionState
即可创建一个随 表单动作被调用 而更新的 state。在调用 useActionState
时在参数中传入现有的表单动作函数以及一个初始状态,无论 Action 是否在 pending 中,它都会返回一个新的 action 函数和一个 form state 以供在 form 中使用。这个新的 form state 也会作为参数传入提供的表单动作函数。
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}>+1</button>
</form>
)
}
form state 是一个只在表单被提交触发 action 后才会被更新的值。如果该表单没有被提交,该值会保持传入的初始值不变。
如果配合 Server Action 一起使用,useActionState
允许与表单交互的服务器的返回值在激活完成前显示。
参数
fn
:当按钮被按下或者表单被提交时触发的函数。当函数被调用时,该函数会接收到表单的上一个 state(初始值为传入的initialState
参数,否则为上一次执行完该函数的结果)作为函数的第一个参数,余下参数为普通表单动作接到的参数。initialState
:state 的初始值。任何可序列化的值都可接收。当 action 被调用一次后该参数会被忽略。- 可选
permalink
: A string containing the unique page URL that this form modifies. For use on pages with dynamic content (eg: feeds) in conjunction with progressive enhancement: iffn
is a server action and the form is submitted before the JavaScript bundle loads, the browser will navigate to the specified permalink URL, rather than the current page’s URL. Ensure that the same form component is rendered on the destination page (including the same actionfn
andpermalink
) so that React knows how to pass the state through. Once the form has been hydrated, this parameter has no effect.
返回值
useActionState
返回一个包含以下值的数组:
- 当前的 state。第一次渲染期间,该值为传入的
initialState
参数值。在 action 被调用后该值会变为 action 的返回值。 - 一个新的 action 函数用于在你的
form
组件的action
参数或表单中任意一个button
组件的formAction
参数中传递。 - 一个
isPending
标识,用于表明是否有正在 pending 的 Transition。
注意
- 在支持 React 服务器组件的框架中使用该功能时,
useActionState
允许表单在服务器渲染阶段时获得部分交互性。当不使用服务器组件时,它的特性与本地 state 相同。 - 与直接通过表单动作调用的函数不同,传入
useActionState
的函数被调用时,会多传入一个代表 state 的上一个值或初始值的参数作为该函数的第一个参数。
用法
使用某个表单动作返回的信息
在组件的顶层调用 useActionState
以获取上一次表单被提交时触发的 action 的返回值。
import { useActionState } from 'react';
import { action } from './actions.js';
function MyComponent() {
const [state, formAction] = useActionState(action, null);
// ...
return (
<form action={formAction}>
{/* ... */}
</form>
);
}
useActionState
返回一个包含以下值的数组:
- 该表单的 当前 state,初始值为提供的 初始 state,当表单被提交后则改为传入的 action 的返回值。
- 传入
<form>
标签的action
属性的 新 action。 - 一个 pending state,可以在处理 action 的过程中使用它。
表单被提交后,传入的 action 函数会被执行。返回值将会作为该表单的新的 当前 state。
传入的 action 接受到的第一个参数将会变为该表单的 当前 state。当表单第一次被提交时将会传入提供的 初始 state,之后都将传入上一次调用 action 函数的返回值。余下参数与未使用 useActionState
前接受的参数别无二致[1]。
function action(currentState, formData) {
// ...
return 'next state';
}
第 1 个示例 共 2 个挑战: 展示表单错误
将 action 包裹进 useActionState
即可展示诸如错误信息或 Server Action 返回的 toast 等信息。
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">加入购物车</button> {isPending ? "加载中……" : message} </form> ); } export default function App() { return ( <> <AddToCartForm itemID="1" itemTitle="JavaScript:权威指南" /> <AddToCartForm itemID="2" itemTitle="JavaScript:优点荟萃" /> </> ) }