React 第四十一节Router 中 useActionData 使用方法案例以及注意事项

一、useActionData前言

useActionData 是 React Router 提供的一个钩子函数,用于获取在路由的 action 函数中返回的数据 。它通常与表单提交(通过 <Form> 组件)配合使用,用于处理表单提交后的服务器响应数据(如错误信息、成功状态等)。

二、useActionData核心用途

处理表单提交结果 :获取表单提交后服务器返回的数据(例如验证错误、成功消息等)。 动态反馈用户 :根据 action 返回的数据更新 UI(如显示错误提示)。 简化数据流:无需手动管理状态,直接通过路由 action 获取数据。

三、useActionData基本流程

用户提交表单(通过 <Form> 组件)。 路由的 action 函数处理提交数据(例如发送到服务器)。 action 返回数据(如错误对象、成功状态)。 组件通过 useActionData() 获取该数据并渲染反馈。

四 useActionData示例:用户登录表单

4.1、 定义路由配置(使用 createBrowserRouter)

javascript 复制代码
// src/main.jsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import LoginPage, { loginAction } from "./LoginPage";

const router = createBrowserRouter([
  {
    path: "/login",
    element: <LoginPage />,
    action: loginAction, // 处理表单提交的 action 函数
  },
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <RouterProvider router={router} />
);

4.2、 定义 Action 函数(处理表单提交)

javascript 复制代码
// src/LoginPage.jsx
export async function loginAction({ request }) {
  const formData = await request.formData();
  const email = formData.get("email");
  const password = formData.get("password");

  // 简单的前端验证
  if (!email.includes("@")) {
    return { error: "邮箱格式不正确" };
  }

  try {
    // 模拟发送登录请求到服务器
    const response = await fetch("/api/login", {
      method: "POST",
      body: JSON.stringify({ email, password }),
    });
    const result = await response.json();

    if (result.success) {
      // 登录成功,重定向到主页
      return redirect("/");
    } else {
      // 返回服务器错误
      return { error: result.message };
    }
  } catch (err) {
    // 网络错误处理
    return { error: "网络请求失败,请重试" };
  }
}

4.3、 在组件中使用 useActionData

javascript 复制代码
// src/LoginPage.jsx
import { Form, useActionData } from "react-router-dom";

export default function LoginPage() {
  const actionData = useActionData(); // 获取 action 返回的数据

  return (
    <div>
      <h1>用户登录</h1>
      <Form method="post">
        {/* 显示错误信息 */}
        {actionData?.error && (
          <div style={{ color: "red" }}>{actionData.error}</div>
        )}

        <input
          type="email"
          name="email"
          placeholder="邮箱"
          required
        />
        <input
          type="password"
          name="password"
          placeholder="密码"
          required
        />
        <button type="submit">登录</button>
      </Form>
    </div>
  );
}

五、参数与返回值

参数:无。

返回值 : 最近一次路由 action 函数返回的数据。 如果没有 提交过 action 或 action 未返回数据,则返回 undefined。

六、注意事项

6.1、必须与 组件配合使用

useActionData 依赖于 React Router 的 <Form> 触发的 action 提交。如果使用普通 <form>手动提交,数据将无法被捕获。

6.2、数据类型一致性

Action 函数可以返回任意类型的数据(对象、字符串等),但组件中需根据实际返回类型处理渲染逻辑。

6.3、作用范围

数据仅与当前路由的 action 关联。如果跳转到其他路由,useActionData 会重置。

6.5、异步处理

Action 函数可以是异步的(如示例中的 async/await),但需确保正确处理加载状态(可配合 useNavigation 显示加载提示)。

七、高级用法:配合 useNavigation 处理加载状态

javascript 复制代码
import { useActionData, useNavigation, Form } from "react-router-dom";

function LoginPage() {
  const actionData = useActionData();
  const navigation = useNavigation();

  // 表单正在提交时显示加载状态
  const isSubmitting = navigation.state === "submitting";

  return (
    <Form method="post">
      {/* 错误提示 */}
      {actionData?.error && <div className="error">{actionData.error}</div>}

      <input name="email" />
      <input name="password" type="password" />

      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? "登录中..." : "登录"}
      </button>
    </Form>
  );
}

八、与 useLoaderData 的区别

useActionData: 获取表单提交后的响应数据 表单提交(POST/PUT/DELETE)触发 useLoaderData: 获取路由初始化时的数据 页面加载或跳转(GET)触发

九、常见场景

9.1、表单验证错误

Action 中校验数据格式,返回错误信息,前端直接渲染。

9.2、API 错误处理

捕获网络请求异常,返回统一错误提示。

9.3、操作成功反馈

返回成功状态并在页面显示"操作成功"提示。

useActionData是 React Router 提供了一种声明式的方式处理表单提交与反馈,用于简化了数据流管理。

相关推荐
anOnion9 小时前
构建无障碍组件之Menu Button pattern
前端·html·交互设计
用户479492835691510 小时前
claude Fable用不了?把Gpt 5.5pro接到你的claude code里
前端·后端
zhangxingchao12 小时前
Kotlin常用的Flow 操作符整理
前端
IT_陈寒14 小时前
React的useState居然还有这种坑?我差点删库跑路
前端·人工智能·后端
Pedantic15 小时前
SwiftUI 手势笔记
前端·后端
橙子家15 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
前端
user205855615181315 小时前
X6 中边悬浮置顶,规避 `mouseleave` 事件丢失问题
前端
李明卫杭州15 小时前
CSS aspect-ratio 属性完全指南
前端
Pedantic17 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端