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 的使用场景
    • 实现适当的加载状态展示
    • 做好错误处理
    • 考虑状态持久化需求
相关推荐
Milk夜雨5 分钟前
Vue.js 入门教程:快速上手
前端·javascript·vue.js
noravinsc6 分钟前
vue md5加密
前端·javascript·vue.js
海的预约8 分钟前
VUE之参数传递
前端·javascript·vue.js
清风细雨_林木木10 分钟前
Element中为什么不使用prop重置无法生效
前端·javascript·vue.js
傻小胖1 小时前
react19新API之use()用法总结
前端·javascript·react.js
傻小胖1 小时前
React 19 新特性总结
前端·javascript·react.js
白嫖叫上我1 小时前
Element修改表格结构样式集合(后续实时更新)
前端·vue.js·elementui
maply3 小时前
基于 Colyseus 的实时消息处理与广播机制
前端·消息队列·node.js·colyseus
芥子沫3 小时前
Safari常用快捷键
前端·safari
lally.3 小时前
2025-1-21 Newstar CTF web week1 wp
前端