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

react-hook-form结合react-number-format使用时isDirty状态异常问题

react-number-format 配合 react-hook-form Controller 组件 isDirty 不更新问题解决方案

问题根因

  • react-hook-form 的 isDirty 和 dirtyFields 基于当前值与默认值的严格相等(===) 逻辑判断,只有两者完全一致时才会判定为未修改。
  • react-number-format 相关字段返回值和默认值类型不匹配:
    • 若取floatValue字段,清空输入时返回值为undefined,undefined === ''结果为false
    • 若错误使用带格式的formattedValue作为提交值,和纯文本默认值的判定也会不匹配
    • 部分特殊场景下清空输入会返回null,同样和空字符串严格相等判断不成立
      因此即使视觉上输入框为空,值和默认值判定为不一致,isDirty始终为true。

修复方案

方案1:统一空值输出类型(最推荐)

在onValueChange回调中做一层值转换,保证清空输入时输出和defaultValue完全一致的类型:

// 示例:defaultValue设置为空字符串的场景
<Controller
  name="currency"
  control={control}
  defaultValue=""
  render={({ field }) => (
    <NumericFormat
      thousandSeparator
      prefix="¥"
      value={field.value}
      onValueChange={(values) => {
        // 空输入时统一转成空字符串,和defaultValue完全匹配
        const submitValue = values.value || '';
        field.onChange(submitValue);
      }}
      onBlur={field.onBlur}
    />
  )}
/>

如果业务需要存储数字类型,把默认值改成undefined即可:

// 示例:值为数字类型的场景
<Controller
  name="currency"
  control={control}
  defaultValue={undefined}
  render={({ field }) => (
    <NumericFormat
      thousandSeparator
      prefix="¥"
      value={field.value}
      onValueChange={(values) => {
        // 空输入时返回undefined,和defaultValue完全匹配
        field.onChange(values.floatValue ?? undefined);
      }}
      onBlur={field.onBlur}
    />
  )}
/>

方案2:自定义脏值判断逻辑

如果不想修改值的输出逻辑,可以在使用isDirty时自定义比较逻辑,兼容空类值的判定:

const { formState, getValues } = useForm({
  defaultValues: { currency: '' }
});

// 自定义脏值判定,兼容空值场景
const isFormDirty = () => {
  const currentVal = getValues('currency');
  // 空字符串、undefined、null都判定为和默认空字符串一致
  if (!currentVal) return false;
  return formState.isDirty;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 08:36:08