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

useForm表单小数值校验触发异常问题求助

问题核心原因
  • 类型不匹配:表单字段默认将输入框onChange返回值识别为字符串类型,但初始化传入的是decimal/number类型的6.77。useForm做值比对时,"6.77" !== 6.77,只要触发输入动作拿到字符串类型值,就会和初始值的number类型判定为不一致,直接触发校验报错。
  • 校验触发逻辑配置问题:如果将校验触发模式设为onChange,且没有配置值类型自动转换逻辑,每一次输入字符变更都会立刻执行校验,无需等失焦或提交动作。
  • 浮点数精度问题:decimal类型转JS原生number时本身存在精度丢失,比如6.77实际存储值可能为6.7700000000000005,哪怕手动输入6.77转成number,和初始decimal值做全等判断也会被判定为不相等。
修复方案
  • 统一表单值类型
    初始化赋值时就把decimal类型默认值转成字符串,和输入框返回的字符串类型保持一致,不要在表单状态里混存number和string两种类型的值:
    const form = useForm({
      defaultValues: {
        // decimal值提前转字符串,和输入值类型对齐
        amount: decimalDefaultValue.toString()
      }
    })
    
  • 按需做类型转换
    表单状态层面统一存字符串类型,等提交取值时再转回业务需要的decimal/number类型即可:
    const handleSubmit = (formValues) => {
      // 提交阶段再做类型转换,不干扰表单内部的值比对逻辑
      const submitParams = {
        amount: new Decimal(formValues.amount)
      }
      // 执行后续提交逻辑
    }
    
  • 调整校验触发时机(可选)
    如果不需要输入时立刻弹出错误,可以把校验模式改成失焦触发,减少输入过程中的无效打断:
    const form = useForm({
      mode: 'onBlur', // 替换默认的onChange触发逻辑
      defaultValues: {
        amount: decimalDefaultValue.toString()
      }
    })
    
  • 特殊场景适配:如果必须在表单状态中存number/decimal类型,注册字段时要配置值转换规则
    通过setValueAs配置项,把输入的字符串自动转换成对应类型,保证和初始值类型完全一致:
    <input
      {...register('amount', {
        // 转number可以直接用内置配置
        // valueAsNumber: true,
        // 转decimal类型自定义转换逻辑
        setValueAs: (inputVal) => new Decimal(inputVal)
      })}
    />
    

注意:判断两个decimal值是否相等时,不要直接用===做全等判断,要调用decimal实例自带的.equals()方法,否则浮点数精度问题会持续导致值校验判定异常。

内容的提问来源于stack exchange,提问作者Minh Lưu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 22:57:33