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

React useForm实现汇率计算器时出现无限循环问题求助

解决React useForm汇率计算器的无限循环问题

你的问题根源在于两个useEffect互相触发更新:修改一个输入框后,对应的useEffect更新另一个输入框,而另一个输入框的变化又会触发原useEffect,形成无限循环。

修复方案一:添加值比较避免重复更新

在调用setValue前,先判断计算出的目标值和当前值是否存在显著差异(考虑浮点精度问题),只有差异足够大时才执行更新,阻断循环:

const {
  register,
  handleSubmit,
  watch,
  setValue,
  formState: { errors },
} = useForm<QuoterInputs>();

const usInput = watch('usInput');
const mxInput = watch('mxInput');

useEffect(() => {
  if (mxInput > 0) {
    const exchange = mxInput / parseFloat(exchangeRate);
    // 浮点计算存在精度误差,用阈值判断是否需要更新
    if (Math.abs(exchange - usInput) > 0.0001) {
      setValue('usInput', exchange, { shouldDirty: false });
    }
  }
}, [exchangeRate, mxInput, setValue, usInput]);

useEffect(() => {
  if (usInput > 0) {
    const exchange = usInput * parseFloat(exchangeRate);
    if (Math.abs(exchange - mxInput) > 0.0001) {
      setValue('mxInput', exchange, { shouldDirty: false });
    }
  }
}, [exchangeRate, usInput, setValue, mxInput]);

修复方案二:改用输入框onChange事件处理

放弃watch+useEffect的组合,直接在输入框的onChange事件中处理计算逻辑。这种方式只有用户手动输入时才会触发更新,程序自动设置的值不会触发onChange,从根源避免循环:

const {
  register,
  handleSubmit,
  setValue,
  formState: { errors },
} = useForm<QuoterInputs>();

const handleUsInputChange = (e) => {
  const value = parseFloat(e.target.value);
  if (!isNaN(value) && value > 0) {
    setValue('usInput', value);
    const mxValue = value * parseFloat(exchangeRate);
    setValue('mxInput', mxValue, { shouldDirty: false });
  } else {
    setValue('usInput', '');
    setValue('mxInput', '', { shouldDirty: false });
  }
};

const handleMxInputChange = (e) => {
  const value = parseFloat(e.target.value);
  if (!isNaN(value) && value > 0) {
    setValue('mxInput', value);
    const usValue = value / parseFloat(exchangeRate);
    setValue('usInput', usValue, { shouldDirty: false });
  } else {
    setValue('mxInput', '');
    setValue('usInput', '', { shouldDirty: false });
  }
};

// 输入框使用方式
<input {...register('usInput')} onChange={handleUsInputChange} type="number" />
<input {...register('mxInput')} onChange={handleMxInputChange} type="number" />

为什么原代码会无限循环?

当你修改mxInput时,第一个useEffect触发并更新usInput;usInput的变化会触发第二个useEffect,进而更新mxInput;mxInput的变化又会再次触发第一个useEffect,如此往复形成循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:20:20