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 的使用场景
    • 实现适当的加载状态展示
    • 做好错误处理
    • 考虑状态持久化需求
相关推荐
界面开发小八哥37 分钟前
可视化工具SciChart如何结合Deepseek快速创建一个React仪表板?
react.js·信息可视化·数据可视化·原生应用·scichart
ObjectX前端实验室2 小时前
个人网站开发记录-引流公众号 & 谷歌分析 & 谷歌广告 & GTM
前端·程序员·开源
CL_IN2 小时前
企业数据集成:实现高效调拨出库自动化
java·前端·自动化
浪九天3 小时前
Vue 不同大版本与 Node.js 版本匹配的详细参数
前端·vue.js·node.js
Java知识技术分享3 小时前
使用LangChain构建第一个ReAct Agent
python·react.js·ai·语言模型·langchain
qianmoQ4 小时前
第五章:工程化实践 - 第三节 - Tailwind CSS 大型项目最佳实践
前端·css
椰果uu4 小时前
前端八股万文总结——JS+ES6
前端·javascript·es6
微wx笑4 小时前
chrome扩展程序如何实现国际化
前端·chrome
~废弃回忆 �༄4 小时前
CSS中伪类选择器
前端·javascript·css·css中伪类选择器
CUIYD_19894 小时前
Chrome 浏览器(版本号49之后)‌解决跨域问题
前端·chrome