Frontend Lab
← 回到所有模式
PA05🧩 Compose · 互動組合表單

Form Validation

表單驗證

難度 ★★★★★標籤 表單 · 驗證 · 狀態機3 min read

模式簡述

表單是「狀態機」最清楚的 UI:pristine → typing → error / valid → submitting → success。 每一步都要有對應的視覺。最常見的雷:未動過就標紅、submitting 中可重複 submit、success 後表單還能改。

乾淨|未動過 — 無錯誤提示

Claude Code Prompt

💬 Claude Code Prompt
參考:PA05 form-validation
技術:React 狀態 + 即時驗證

具體行為:
- pristine(未動過):純背景,無錯誤
- typing:每 keystroke 即時驗證,錯誤即時顯示
- error:紅 border + 紅文字錯誤訊息
- submitting:按鈕 disabled + spinner
- success:綠色 border + Check icon,按鈕 disabled

驗證規則:
- Email: 必須包含 @ 跟 . 的合法格式
- Password: 至少 8 字元

限制:
- pristine 絕對不顯示錯誤(使用者還沒輸入就被罵很不爽)
- submitting 期間鎖按鈕,避免重複送出
- 錯誤訊息一定要具體(不要寫「格式錯誤」,寫「需包含 @」)

完整程式碼

FormValidation.tsx
'use client'

import { useState } from 'react'

type FormState = 'pristine' | 'typing' | 'error' | 'submitting' | 'success'

export function FormValidation() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [state, setState] = useState<FormState>('pristine')

const emailValid = /.+@.+\..+/.test(email)
const passwordValid = password.length >= 8

const showEmailError = state === 'typing' && email.length > 0 && !emailValid
const showPasswordError = state === 'typing' && password.length > 0 && !passwordValid

function handleSubmit() {
  if (!emailValid || !passwordValid) {
    setState('error')
    return
  }
  setState('submitting')
  setTimeout(() => setState('success'), 1200)
}

return (
  <form onSubmit={e => { e.preventDefault(); handleSubmit() }}>
    <input
      value={email}
      onChange={e => { setEmail(e.target.value); setState('typing') }}
      className={showEmailError ? 'border-red-500' : 'border-border'}
    />
    {showEmailError && <p className="text-red-500">Email 格式不正確</p>}
    {/* ...password 同理... */}
    <button disabled={state === 'submitting' || state === 'success'}>
      {state === 'submitting' ? '送出中⋯' : state === 'success' ? '已送出' : '登入'}
    </button>
  </form>
)
}

何時用

  • ✅ 登入 / 註冊
  • ✅ 結帳 / 訂單
  • ✅ 任何需要明確「送出」動作的輸入

何時別用

  • ❌ 搜尋框(即時查就好,不需要 submit)
  • ❌ Autosave 表單(用 toast 提示,不用 submitting 狀態)
  • ❌ 單一欄位的設定(用 input + blur 即可)

我踩過的坑

  1. pristine 就標紅:使用者進到頁面看到一片紅,瞬間想關掉。 一定要等使用者動過才開始驗證。

  2. submitting 期間沒鎖按鈕:使用者連點 3 下,後端收到 3 筆相同訂單。 disabled + 換文案是基本盤。

  3. 錯誤訊息寫「格式錯誤」:使用者:「哪裡錯了?」要寫具體: 「Email 需包含 @」、「密碼至少 8 字元」。

相關模式

  • 暫無

搜尋

按 ⌘K 隨時開啟