表單驗證

表單驗證

本指南將逐步介紹一個簡單的註冊表單實作。您可能會希望將這些概念與第三方驗證函式庫和錯誤組件配對使用,但本指南僅著重於 React Router 的運作機制。

1. 設定

我們將從建立一個帶有表單的基本註冊路由開始。

import {
  type RouteConfig,
  route,
} from "@react-router/dev/routes";

export default [
  route("signup", "signup.tsx"),
] satisfies RouteConfig;
import type { Route } from "./+types/signup";
import { useFetcher } from "react-router";

export default function Signup(_: Route.ComponentProps) {
  let fetcher = useFetcher();
  return (
    <fetcher.Form method="post">
      <p>
        <input type="email" name="email" />
      </p>

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

      <button type="submit">Sign Up</button>
    </fetcher.Form>
  );
}

2. 定義 Action

在此步驟中,我們將在與 `Signup` 組件相同的文件中定義伺服器 `action`。請注意,此處的目的是提供所涉及機制的廣泛概述,而不是深入研究表單驗證規則或錯誤物件結構。我們將使用電子郵件和密碼的基本檢查來演示核心概念。

import type { Route } from "./+types/signup";
import { redirect, useFetcher, data } from "react-router";

export default function Signup(_: Route.ComponentProps) {
  // omitted for brevity
}

export async function action({
  request,
}: Route.ActionArgs) {
  const formData = await request.formData();
  const email = String(formData.get("email"));
  const password = String(formData.get("password"));

  const errors = {};

  if (!email.includes("@")) {
    errors.email = "Invalid email address";
  }

  if (password.length < 12) {
    errors.password =
      "Password should be at least 12 characters";
  }

  if (Object.keys(errors).length > 0) {
    return data({ errors }, { status: 400 });
  }

  // Redirect to dashboard if validation is successful
  return redirect("/dashboard");
}

如果發現任何驗證錯誤,它們會從 `action` 返回到 fetcher。這是我們向 UI 發出信號,表示需要更正某些內容的方式,否則使用者將被重新導向到儀表板。

請注意 `data({ errors }, { status: 400 })` 呼叫。設定 400 狀態是 Web 標準的方式,向客戶端發出存在驗證錯誤(錯誤請求)的信號。在 React Router 中,只有 200 狀態碼會觸發頁面資料重新驗證,因此 400 可以防止這種情況。

3. 顯示驗證錯誤

最後,我們將修改 `Signup` 組件以顯示來自 `fetcher.data` 的驗證錯誤(如果有的話)。

export default function Signup(_: Route.ComponentProps) {
  let fetcher = useFetcher();
  let errors = fetcher.data?.errors;
  return (
    <fetcher.Form method="post">
      <p>
        <input type="email" name="email" />
        {errors?.email ? <em>{errors.email}</em> : null}
      </p>

      <p>
        <input type="password" name="password" />
        {errors?.password ? (
          <em>{errors.password}</em>
        ) : null}
      </p>

      <button type="submit">Sign Up</button>
    </fetcher.Form>
  );
}
文件和範例 CC 4.0