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
相关产品推荐
相关产品推荐

