react中hooks之 React 19 新 Hooks useActionState & useFormStatus用法总结

React 19 新 Hooks 使用指南: useActionState & useFormStatus

目录

  1. useActionState
  2. useFormStatus
  3. 最佳实践

useActionState

概述

useActionState 是 React 19 引入的新 Hook,用于处理表单 action 的状态更新。它允许你基于表单 action 的结果来更新组件状态。

官网

基本语法

typescript 复制代码
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);

参数说明

  1. fn: 表单提交时调用的函数

    • 接收上一次状态作为第一个参数
    • 接收表单数据作为后续参数
    • 返回新的状态
  2. initialState: 初始状态值

    • 可以是任何可序列化的值
    • 在 action 首次调用后会被忽略
  3. permalink?: (可选) 唯一页面 URL

    • 用于动态内容页面(如 feeds)
    • 配合渐进式增强使用
    • 在 JavaScript bundle 加载前提交表单时使用

返回值

typescript 复制代码
type UseActionStateReturn<T> = [
  T,                    // 当前状态
  (formData: FormData) => void,  // 表单 action
  boolean               // 是否处于 pending 状态
];

使用示例

typescript 复制代码
async function increment(previousState: number, formData: FormData) {
  return previousState + 1;
}

function Counter() {
  const [count, formAction, isPending] = useActionState(increment, 0);
  
  return (
    <form>
      <p>Count: {count}</p>
      <button formAction={formAction} disabled={isPending}>
        {isPending ? 'Incrementing...' : 'Increment'}
      </button>
    </form>
  );
}

useFormStatus

概述

useFormStatus 是一个专门用于获取父级表单提交状态的 Hook。它提供了表单提交过程中的详细状态信息。

基本语法

typescript 复制代码
const { pending, data, method, action } = useFormStatus();

使用限制

  1. 必须在 <form> 元素内部使用
  2. 必须是表单的子组件
  3. 不能在表单 action 处理函数内使用

使用示例

typescript 复制代码
function SubmitButton() {
  const { pending, data } = useFormStatus();
  
  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

function Form() {
  async function formAction(formData: FormData) {
    // 处理表单提交
  }

  return (
    <form action={formAction}>
      <input name="name" />
      <SubmitButton />
    </form>
  );
}

最佳实践

  1. Server Actions 集成
typescript 复制代码
// 服务端 action
async function updateUser(prevState: any, formData: FormData) {
  'use server';
  const name = formData.get('name');
  await db.updateUser({ name });
  return { message: 'Updated!' };
}

// 客户端组件
function UserForm() {
  const [state, formAction] = useActionState(updateUser, null);
  return (
    <form action={formAction}>
      <input name="name" />
      <SubmitButton />
      {state?.message && <p>{state.message}</p>}
    </form>
  );
}
  1. 错误处理
typescript 复制代码
async function submitForm(prevState: any, formData: FormData) {
  try {
    const result = await submitData(formData);
    return { data: result, error: null };
  } catch (e) {
    return { data: null, error: e.message };
  }
}
  1. 渐进式增强
typescript 复制代码
function CommentForm({ postId }) {
  const [state, formAction] = useActionState(
    submitComment,
    null,
    `/posts/${postId}#comments` // permalink for progressive enhancement
  );
  
  return (
    <form action={formAction}>
      {/* 表单内容 */}
    </form>
  );
}

注意事项

  1. useActionState:

    • 与框架的 Server Components 集成时支持服务端渲染
    • 函数签名与直接使用表单 action 不同
    • 支持渐进式增强
  2. useFormStatus:

    • 只能在表单子组件中使用
    • 提供实时的表单状态
    • 适合构建可复用的表单组件
  3. 性能考虑:

    • 自动处理并发更新
    • 支持 Suspense 集成
    • 优化服务端状态同步

最佳实践补充

  1. 状态复用
typescript 复制代码
// 创建可复用的表单状态 hook
function useFormWithStatus<T>(action: string) {
  const formStatus = useFormStatus();
  const [formState, setFormState] = useState<T | null>(null);

  useEffect(() => {
    if (!formStatus.pending && formStatus.data) {
      setFormState(Object.fromEntries(formStatus.data.entries()) as T);
    }
  }, [formStatus.pending, formStatus.data]);

  return {
    ...formStatus,
    formState
  };
}
  1. 类型安全处理
typescript 复制代码
// 为 useActionState 添加类型
interface UserData {
  id: string;
  name: string;
  email: string;
}

const [updateUser, { data }] = useActionState<UserData, Partial<UserData>>(
  async (updates) => {
    const response = await fetch('/api/user', {
      method: 'PATCH',
      body: JSON.stringify(updates)
    });
    return response.json();
  }
);

// TypeScript 会正确推断 data 的类型为 UserData | null

总结

  1. useActionState 优点:

    • 简化异步状态管理
    • 提供完整的状态信息
    • 易于集成错误处理
    • 支持类型安全
  2. useFormStatus 优点:

    • 专注于表单状态
    • 提供详细的提交信息
    • 易于实现加载指示器
    • 支持复杂表单流程
  3. 使用建议:

    • 合理区分两个 Hook 的使用场景
    • 实现适当的加载状态展示
    • 做好错误处理
    • 考虑状态持久化需求
相关推荐
不浪brown26 分钟前
开源!矢量建筑白模泛光特效以及全国77个大中城市的矢量shp数据获取!
前端·cesium
山有木兮木有枝_27 分钟前
JavaScript 数据类型与内存分配机制探究
前端
小小小小宇33 分钟前
前端 异步任务并发控制
前端
bysking1 小时前
【27-vue3】vue3版本的"指令式弹窗"逻辑函数createModal-bysking
前端·vue.js
LuckySusu1 小时前
【HTML篇】script`标签中的 defer 与 async:深入解析异步加载 JavaScript 的差异
前端·html
CAD老兵1 小时前
在 TypeScript 中复用已有 Interface 的部分属性:完整指南
前端
龚思凯1 小时前
Vue 3 中 watch 监听引用类型的深度解析与全面实践
前端·vue.js
于冬恋1 小时前
Web后端开发(请求、响应)
前端
red润1 小时前
封装hook,复刻掘金社区,暗黑白天主题切换功能
前端·javascript·vue.js
Fly-ping1 小时前
【前端】vue3性能优化方案
前端·性能优化