You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用react-hook-form实现数学题校验的反垃圾表单功能

核心问题

你的算术验证码校验失效,是因为对react-hook-form的规则配置理解错了:

  • register配置项里的value字段是用来给输入框设置初始值的,根本没有值相等校验的作用,你写在这个字段里的错误提示永远不会触发
  • 表单reset之后没有刷新算术题,提交一次后题目不变,很容易被脚本批量提交
  • number类型输入框返回的表单值默认是字符串,直接和数字类型的正确答案对比会出现类型错误,导致就算算对也可能被误判
修复方案

把不存在的value校验换成react-hook-form原生支持的validate自定义校验规则,提交成功后自动刷新新的算术题,对比答案时统一转成数字类型避免类型误差,修正后的代码如下:

import { useState, useMemo } from 'react'
import { useForm } from 'react-hook-form'

// 生成区间内随机整数
function generateRandomIntegerInRange(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min
}

function Contact_ContactForm_Form() {
  const [spamCheck, setSpamCheck] = useState({
    num1: generateRandomIntegerInRange(0, 10), 
    num2: generateRandomIntegerInRange(0, 10),
  })

  const spamCheckAnswer = useMemo(
    () => spamCheck.num1 + spamCheck.num2,
    [spamCheck]
  )

  const { register, handleSubmit, reset, formState: { errors }} = useForm()

  const onSubmit = (data) => {
    // 此处写实际业务提交逻辑
    reset()
    // 提交成功后生成新的验证题
    setSpamCheck({
      num1: generateRandomIntegerInRange(0, 10),
      num2: generateRandomIntegerInRange(0, 10)
    })
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        type='email'
        {...register('email', {
          required: { message: '请输入邮箱地址', value: true },
          minLength: { message: "邮箱长度不符合要求", value: 4 },
          pattern: {
            value: /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
            message: '邮箱格式无效',
          },
        })}
      />
      <input
        type='number'
        placeholder={`${spamCheck.num1} + ${spamCheck.num2} = ?`}
        {...register('spamCheck', {
          required: {
            message: "请完成算术验证",
            value: true,
          },
          // 自定义校验判断答案是否正确
          validate: (inputVal) => Number(inputVal) === spamCheckAnswer || "计算错误,请重新输入"
        })}
      />
      <input type='submit' />
      {errors.email && <div>{errors.email.message}</div>}
      {errors.spamCheck && <div>{errors.spamCheck.message}</div>}
    </form>
  )
}
export default Contact_ContactForm_Form
补充说明
  • 这种纯前端算术题只能拦住最基础的垃圾脚本,防护能力很弱,生产环境建议搭配后端接口限流、提交一次性token、服务端二次校验答案的逻辑一起用,不然很容易被绕过
  • 如果要提升前端验证的门槛,可以随机切换加减乘除运算,调整数字范围,不要固定用0-10的加法

内容的提问来源于stack exchange,提问作者JordyJordyJordyJordan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:06:22