
在 React 表单中实现 USD/MXN 双向联动输入时,若未加防抖或值比对,极易触发 useEffect 的循环调用,导致页面卡顿或崩溃;本文提供基于 useForm 和 watch 的稳定解决方案。
在 react 表单中实现 usd/mxn 双向联动输入时,若未加防抖或值比对,极易触发 useeffect 的循环调用,导致页面卡顿或崩溃;本文提供基于 `useform` 和 `watch` 的稳定解决方案。
在构建实时汇率换算器时,常见需求是:用户修改任一货币输入框(如 USD 或 MXN),另一字段自动按当前汇率同步更新。但直接为两个 useEffect 分别监听并调用 setValue 会形成「A → B → A → B…」的无限更新链——因为 setValue 会触发 watch 值变更,进而再次触发另一个 effect。
核心问题在于缺乏更新守卫:每次计算后都无条件调用 setValue,即使目标值与当前值完全一致,也会触发冗余渲染和副作用重执行。
✅ 正确做法是 在 setValue 前严格比对计算结果与当前值,仅当值真正变化时才更新:
const { register, watch, setValue } = useForm<quoterinputs>();
const usInput = watch('usInput');
const mxInput = watch('mxInput');
// MXN → USD:仅当计算出的 USD 值 ≠ 当前 usInput 时才更新
useEffect(() => {
if (mxInput > 0) {
const calculatedUsd = mxInput / parseFloat(exchangeRate);
// ⚠️ 关键守卫:避免无意义 setValue
if (calculatedUsd !== usInput) {
setValue('usInput', calculatedUsd, { shouldValidate: false });
}
}
}, [exchangeRate, mxInput, usInput, setValue]);
// USD → MXN:同理,避免反向触发
useEffect(() => {
if (usInput > 0) {
const calculatedMxn = usInput * parseFloat(exchangeRate);
if (calculatedMxn !== mxInput) {
setValue('mxInput', calculatedMxn, { shouldValidate: false });
}
}
}, [exchangeRate, usInput, mxInput, setValue]);</quoterinputs>
? 注意事项:
- 使用 !== 进行严格数值比较(注意浮点精度问题,生产环境建议用 Math.abs(a - b)
- 添加 { shouldValidate: false } 防止每次 setValue 都触发校验,提升性能;
- watch 返回的是受控值,确保输入框已通过 register 正确绑定;
- 若汇率 exchangeRate 来自异步 API,需加入 loading 状态判断,避免初始空值导致 NaN 计算。
? 进阶优化:可封装为自定义 Hook(如 useBidirectionalCurrency),复用逻辑并内置精度处理与防抖,进一步提升可维护性。该方案已在多个金融类表单中验证稳定,彻底消除无限循环风险。











